Python has at least eight(?!) ways to execute system commands, and most of them are injectable if you pass user input. We maintain a command injection cheat sheet that covers the common patterns and their fixes. A few highlights: Vulnerable: subprocess.call("grep -R {} .".format(user_input), shell=True) os.system("grep -R {} .".format(user_input)) Safe: subprocess.run(["grep", "-R", user_input, "."]) The fix is almost always the same: use array-based arguments instead of string formatting, and keep `shell=False` (which is the default). When you pass an array, each element becomes a separate argument. The shell never interprets the input, so injection is structurally impossible. Semgrep has pre-built rules for all of these: - python.lang.security.audit.dangerous-subprocess-use - python.lang.security.audit.subprocess-shell-true - python.lang.security.audit.dangerous-system-call Run semgrep --config "p/python" on your codebase and these rules are included. Or browse the full cheat sheet at https://lnkd.in/gYRS2SyS to see all the patterns covered for Python, Java, JavaScript, Go, and Ruby. #SAST #AppSec
Prevent Command Injection in Python with Array-Based Arguments
More Relevant Posts
-
Python developers have accepted forks and monkey patches for too long. 𝗺𝗼𝗱𝘀𝗵𝗶𝗺 is a cleaner way to customize packages without touching their code. It gives Python developers a way to override and customize existing packages without editing the original source code, which immediately makes it stand out from the usual mix of forks, vendoring, and brittle monkey patches. That matters because most teams do not want to maintain a permanent fork of a dependency just to patch one behavior, test one variation, or add one missing feature that the upstream package does not support yet. What I like about modshim is that it approaches this problem with a cleaner mental model, where the original package stays intact and your changes live in a separate layer that can be mounted through Python’s import system. In practice, that means you can adapt third party packages in a way that feels far more deliberate, maintainable, and reversible than the hacks many of us have quietly accepted as normal in production code. It is the kind of tool that feels small at first glance, but the more Python you have written, the more obvious its value becomes. --- ♻️ Found this useful? Share it with another builder. ➕ For daily practical AI and Python posts, follow Banias Baabe.
To view or add a comment, sign in
-
-
Todays task focused on port scanning using python. Although there are modern tools that deal with this, I decided to learn it just on a foundational level as I have worked with apps like Nmap and will at some point be introduced to Masscan in the near future. Also I had an issue with Github regarding push comment as there was an issue with the permission granting from the repository , and other issues. commands in the python script that - import socket - this is Pythons network library - allows Python to interact with the network or port - target = input(Enter target IP: ") - choose which machine to scan Also learned that ports start from 0 and not necessarily from Port 21 which is the File Transfer Protocol, so another added information in my memory bank. - for port in range(1, 1025) - this specific ports are ports that well-known, example beig ssh, telnet SMTP etc I always encountered interesting variables, that when broken down sound so much better 😂 ; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s = socket.socket - simply means CREATING A NETWORK CONNECTION - (socket.AF.INET) - simply means IPv4 - socket.SOCK_STREAM simply - means the TCP protocol Then I also upgraded the port scanner using MULTITHREADING, which simply means upgrading the port scan to scan the ports simultaneously instead of scanning individually. commands I learned are; - import thread - network library allows Python to run multiple tasks simultaneously. - thread = threading.Thread(target=scan_port, args=(port,)) - thread = create a new thread -target=scan_port =give it the scan_port function -args=(port,) = pass the port number as input Since last weekend I practiced the Port protocols, this weekend I will be focusing on Security ac
To view or add a comment, sign in
-
🔧 Creating a Python Shared Object with C++ Python is powerful, but sometimes you need the speed and flexibility of C++. The good news? You can compile C++ code into a shared object and use it directly in Python. This approach unlocks powerful possibilities: - ⚡ Performance: Machine code runs dozens of times faster than interpreted Python. - 🔒 Security: You can embed anti reverse-engineering techniques, similar to how tools like PyArmor work. - 🛠️ Flexibility: Build any C++ functionality and seamlessly integrate it into Python projects. This format does three things: - Hooks attention with benefits first. - Shows authority by outlining the process clearly but concisely. - Invites engagement by ending with a question. How It Works (High-Level) 1. Write your C++ function (e.g., say_hello that prints from C++). 2. Define a Python module interface using Python.h. 3. Use setup.py with setuptools to compile your C++ into a .pyd (Windows) or .so (Linux) file. 4. Import it in Python just like any other module: `python import example example.say_hello() ` 🛠 Step-by-Step Process Step 1: Project Structure ` your_project/ │ ├── example.cpp └── setup.py ` Step 2: Write C++ Code `cpp include <Python.h> static PyObject say_hello(PyObject self, PyObject* args) { printf("Hello from C++!\n"); PyRETURNNONE; } ` Step 3: Create setup.py `python from setuptools import setup, Extension example_module = Extension( 'example', sources=['example.cpp'], ) setup( name='example', version='1.0', description='Example C++ extension for Python', extmodules=[examplemodule], ) ` Step 4: Build the Shared Object `bash python3 setup.py build ` Step 5: Install the Module Locate the .pyd (Windows) or .so (Linux) file in the build folder and copy it where needed. Step 6: Use in Python `python import example example.say_hello() ` ✅ Key Point : Using setup.py makes compiling and installing C++ extensions for Python straightforward. This approach combines Python’s simplicity with C++’s speed and control — a powerful tool for developers working on performance-critical or security-conscious projects. #Python #Cplusplus #PythonExtensions #CodingTips #SoftwareDevelopment #ProgrammingLife #CodeOptimization
To view or add a comment, sign in
-
Day 7 of my Python journey — begins with something that powers every feature in every application you have ever used. Conditional logic. Last week I learned to store data. This week I learn to make decisions with it. Every login button, every payment validation, every content filter, every recommendation algorithm — all of it runs on if/elif/else conditions. Today I went deeper than the syntax. The truthy and falsy list — what every Python developer knows by heart These values are all "falsy" in Python — they evaluate as False in any condition: 0 | 0.0 | "" | [] | {} | None | False Everything else is truthy. Why this matters in real code: if username: # True only if username is not empty string AND not None if items_in_cart: # True only if cart has at least one item if account_balance: # True only if balance is non-zero Professional Python uses this constantly. It replaces multiple explicit checks with one clean condition. Not knowing this means writing more code that does less. Short-circuit evaluation — used intentionally, not just as an optimisation if user and user.is_verified and user.has_access: grant_permission() Python evaluates left to right and stops as soon as the result is determined. If user is None, Python never tries to access user.is_verified — which would crash. This chained pattern is used in every permission system, every authentication flow, and every null-safety check in professional Python code. The boundary value lesson My first grade classifier had elif score > 90 for grade A. A score of exactly 90 got classified as B. The correct condition: elif score >= 90. Boundary values are where conditional logic fails most often. Every if/elif chain must be tested at the exact boundary — not just in the middle of each range. This is the difference between code that works and code that passes testing. What I built today: grade classifier, leap year validator, ATM withdrawal system, and a login validator — all handling edge cases and boundaries correctly. The logic is building. #Python#Day7#ConditionalLogic#SelfLearning#CodewithHarry#PythonBasics#w3schools.com#W3Schools
To view or add a comment, sign in
-
🔧 COM interop in a Python process is a special kind of fun. I promised this story in my last post. Here it is. I had the MCP server wired up. GRAccess calls were working in my test script. I plugged it into the MCP tool handler, asked Claude a question about my System Platform galaxy, and got back: "CoInitialize has not been called." One line. No stack trace. Just a flat refusal, two parts of the system weren't set up to talk to each other on the same thread. Sounds simple. It is not. GRAccess, like a lot of industrial SDKs, uses COM under the hood, and its COM objects expect to be called from a single, specifically initialized thread. That's fine in a test script. It's a problem when MCP tool calls arrive asynchronously, the LLM might chain multiple calls in a single turn, and Python's asyncio is running on its own event loop in a different thread entirely. When you get this wrong, COM doesn't throw a clean error. It fails in creative ways. Silent hangs. Garbage return values. Access violations that crash the whole process. Or worst of all: it returns data that looks right but isn't. The first fix everyone tries: sprinkle CoInitialize() calls at the top of every tool handler. That works, until two tools run concurrently. Now you've got two threads fighting over an object that was never designed to be shared. What actually works: one dedicated thread that owns all GRAccess calls. Initialize COM once on that thread. Tool handlers post requests to it via a queue, wait for results. Forty lines of code. The same message-pump pattern Windows UIs have used for decades. Three days of debugging for forty lines of code. Not because the solution is complicated, but because COM threading bugs don't give you error messages. They give you wrong answers. In an industrial system, that's not a minor inconvenience. That's a credibility problem. If you know someone wrangling COM objects from Python in 2026, send them this post. It might save them a few days. Next: how I designed the MCP tools themselves; what to expose, what to hide, and why the granularity of your tool interface matters more than you'd think. 💬 What's the worst "it looked right but wasn't" bug you've dealt with in an industrial system? #AVEVA #SystemPlatform #IndustrialAI #SCADA #MCP #Python
To view or add a comment, sign in
-
-
I used to hate lazy imports in Python. Coming from C++, there's something deeply uncomfortable about importing inside a method. You want your dependencies declared upfront, visible, accounted for — not buried somewhere in the call stack. But that discomfort was baggage, not wisdom. If you've been avoiding them out of habit, it's worth a second look. https://lnkd.in/g-4dkyH8
To view or add a comment, sign in
-
⛔ Python Tip: Don’t Use if Statements to Count Items. Use defaultdict You have a list of items, and you want to know how many times each item appears in the list; a common beginner pattern is to write something that looks like this: counts = {} for item in items: if item in counts: counts[item] += 1 else: counts[item] = 1 This works, but it's quite verbose and therefore not very Pythonic. The best way to do it is to use `defaultdict` from the `collections` module. Here is how the code will look using this method: from collections import defaultdict counts = defaultdict(int) for item in items: counts[item] += 1 A defaultdict is a special type of dictionary from Python’s collections module. The key idea is that it automatically creates a default value for keys that do not yet exist. In this code, when we write: counts = defaultdict(int) We tell Python that if a key is missing, create it and assign it the default value returned by `int()`, which is 0. This means every new key starts at 0, and 1 is added to it if it occurs more than once. No if statement is required. This is much better: it is less verbose, requires no manual checks, and is therefore less prone to error. 🔑 You want more Python tips? Check out the Python Tips and Tricks: A Collection of 100 Basic & Intermediate Tips & Tricks Link: https://lnkd.in/eyq2Yg7F
To view or add a comment, sign in
-
-
Understanding How Python Code Runs: From Source Code to Execution When we write Python programs, it may appear that the code runs directly after we execute it. However, behind the scenes, Python follows a well-defined process before producing the final output. Here is a step-by-step overview of how Python code is executed: 1️⃣ Writing the Source Code The process begins when a developer writes Python code in a file with the ".py" extension (for example, "main.py"). This file contains the human-readable instructions written using Python syntax. 2️⃣ Python Interpreter Reads the Code When the program is executed (e.g., "python main.py"), the Python interpreter reads the source code. Unlike compiled languages such as C or C++, Python does not directly convert code into machine code. 3️⃣ Compilation to Bytecode The interpreter first compiles the source code into an intermediate format called bytecode. Bytecode is a low-level, platform-independent representation of the program instructions. 4️⃣ Storage in "__pycache__" The generated bytecode is often stored in the "__pycache__" directory as ".pyc" files. This allows Python to reuse the compiled bytecode in future executions, improving performance. 5️⃣ Execution by the Python Virtual Machine (PVM) Finally, the Python Virtual Machine (PVM) reads the bytecode and executes it instruction by instruction. The PVM acts as a runtime engine that translates bytecode into operations understandable by the underlying system. 📌 In Summary: Python Execution Flow → "Source Code (.py) → Bytecode (.pyc) → Python Virtual Machine → Output" #Python #Programming #SoftwareDevelopment #Coding #PythonInternals #Developers #LearningPython
To view or add a comment, sign in
-
-
**Dangerous Python** **Artifact #1 – a function that changes its own code** Most programmers assume one simple rule: if a function is called f, it always does the same thing. Python allows you to break that assumption. Not through eval. Not through dynamic imports. Directly inside the function object itself. In Python, every function has an attribute called __code__. This is the bytecode, the actual execution engine of the function. And it can be replaced while the program is running. Below the post you can see a minimal example. _________________________________________________________________ **What just happened?** At first the function f behaves normally. f(x) = x + 1 But when the condition x == 7 appears, a surgical operation happens: f.__code__ = ... From that moment on, the function behaves completely differently. The same object. The same name. A different engine. **Why is this dangerous?** This mechanism breaks several fundamental assumptions of programming. 1. Code stops being stable over time A function may do one thing at the beginning of the program and something entirely different five seconds later. 2. Debugging becomes harder Stack traces and code inspection may show one thing while the runtime is executing something else. 3. Tests may become unstable If tests run in a different order, the program may behave differently. **Why does Python allow this?** Because Python is not only a programming language. It is a runtime manipulation system. Functions, classes, and modules are just objects. And objects can be modified. This power is useful in: frameworks plugin systems instrumentation code analysis tools But in normal application code, this is closer to a museum artifact than a design pattern. PYTHON ALLOWS SOMETHING MOST LANGUAGES FORBID: A FUNCTION CAN REMAIN THE SAME FUNCTION… AND STILL CHANGE ITS CODE WHILE THE PROGRAM IS RUNNING.
To view or add a comment, sign in
-
-
Python is dynamic. Clojure is dynamicer? (defn g [x] (if (= 7 x) (do (defn g [y] (* y y)) (g x)) (+ 1 x))) [(g 1) (g 7) (g 2)] ;=> [2 49 4] Being able to do this with ease is what keeps me happy as a programmer.
**Dangerous Python** **Artifact #1 – a function that changes its own code** Most programmers assume one simple rule: if a function is called f, it always does the same thing. Python allows you to break that assumption. Not through eval. Not through dynamic imports. Directly inside the function object itself. In Python, every function has an attribute called __code__. This is the bytecode, the actual execution engine of the function. And it can be replaced while the program is running. Below the post you can see a minimal example. _________________________________________________________________ **What just happened?** At first the function f behaves normally. f(x) = x + 1 But when the condition x == 7 appears, a surgical operation happens: f.__code__ = ... From that moment on, the function behaves completely differently. The same object. The same name. A different engine. **Why is this dangerous?** This mechanism breaks several fundamental assumptions of programming. 1. Code stops being stable over time A function may do one thing at the beginning of the program and something entirely different five seconds later. 2. Debugging becomes harder Stack traces and code inspection may show one thing while the runtime is executing something else. 3. Tests may become unstable If tests run in a different order, the program may behave differently. **Why does Python allow this?** Because Python is not only a programming language. It is a runtime manipulation system. Functions, classes, and modules are just objects. And objects can be modified. This power is useful in: frameworks plugin systems instrumentation code analysis tools But in normal application code, this is closer to a museum artifact than a design pattern. PYTHON ALLOWS SOMETHING MOST LANGUAGES FORBID: A FUNCTION CAN REMAIN THE SAME FUNCTION… AND STILL CHANGE ITS CODE WHILE THE PROGRAM IS RUNNING.
To view or add a comment, sign in
-