Skip to content

Commit e66a65a

Browse files
Appyclaude
andcommitted
chore(release): pseudonymize attribution and scrub private-upstream references
- LICENSE/pyproject: credit "Appy" instead of legal name, consistent with the pseudonymous git identity. - Remove comments naming the private upstream's internal structure (engine/config/facts docstrings). - Soften README and rule/config comments that disclosed held-back internals (taint-tracking loader, production-tuned weights/threshold). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9821367 commit e66a65a

8 files changed

Lines changed: 17 additions & 22 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ artifact_cache/
2121
.coverage
2222
.DS_Store
2323

24-
# Agent guidance — not shipped product, references private upstream
24+
# Local agent guidance — not part of the published project
2525
CLAUDE.md

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2026 Ankit Prateek
3+
Copyright (c) 2026 Appy
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ diffs each against its prior version, runs a **community-extensible rules engine
55
escalates anything suspicious to an LLM reviewer for a verdict — so a malicious update can be caught and
66
reported **before** it spreads.
77

8-
PyDiffWatch is the open-source sibling of a private upstream scanner. The pipeline, the rules engine, and
9-
a starter ruleset are all here and MIT-licensed; you bring your own compute, your own LLM endpoint, and
10-
your own rules.
8+
The pipeline, the rules engine, and a starter ruleset are all here and MIT-licensed; you bring your own
9+
compute, your own LLM endpoint, and your own rules.
1110

1211
**New here?** [HOWTO.md](HOWTO.md) is a step-by-step setup-to-deployment guide (endpoints, API keys,
1312
cron/systemd/Docker/CI). This README is the overview.
@@ -118,14 +117,12 @@ code. Example: flag a base64 decode and an exec/eval co-occurring in the same ch
118117
See **[RULES.md](RULES.md)** for the full schema, the predicate reference, and worked examples — written
119118
for both humans and LLM assistants, so you (or your agent) can author a valid rule in a few minutes.
120119
121-
## What's here vs. upstream
120+
## What's here
122121
123122
PyDiffWatch ships the full pipeline and a baseline ruleset: import-bound primitive detection, auto-exec
124123
location weighting, decode/fetch/credential combos, foreign-language-source, added-dependency reputation,
125-
and maintainer-change signals. The private upstream additionally carries a dataflow taint-tracking
126-
loader detector and production-tuned weights; those are not part of this open release. The engine and
127-
rule format here are the same ones the community extends — and the same ones upstream publishes vetted
128-
rules into over time.
124+
and maintainer-change signals. The scoring weights and threshold are baselines you can tune. The engine
125+
and rule format here are the ones the community extends.
129126
130127
## License
131128

pydiffwatch/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Config:
2929
db_path: Path = Path(".diffwatch/diffwatch.sqlite")
3030
cache_dir: Path = Path(".diffwatch/artifact_cache")
3131
lock_path: Path = Path(".diffwatch/diffwatch.lock")
32-
# containment caps (ported verbatim from main DiffWatch)
32+
# containment caps
3333
max_download_bytes: int = 50 * 1024 * 1024
3434
max_members: int = 2000
3535
max_member_bytes: int = 10 * 1024 * 1024
@@ -44,7 +44,7 @@ class Config:
4444
max_releases_per_run: int = 2000
4545
fetch_concurrency: int = 4
4646
new_package_policy: str = "surface" # "surface" | "skip" | "full"
47-
threshold_t: float = 40.0 # baseline default; production-tuned value held back in main
47+
threshold_t: float = 40.0 # baseline default; tune for your tolerance
4848
pypi_base: str = "https://pypi.org"
4949
webhook_url: str | None = None
5050
evidence_max_chars: int = 200_000

pydiffwatch/engine.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"""Rules-engine triage: build facts from a diff, run the loaded ruleset over them, sum weights.
22
3-
Drop-in replacement for main DiffWatch's hardwired `triage.triage`, emitting the same public types
4-
(`FiredRule`, `TriageResult`) so the orchestrator/notifier/store are unchanged. The detection opinions
3+
Emits `FiredRule` / `TriageResult` for the orchestrator/notifier/store. The detection opinions
54
live entirely in the loaded rules (`rules/community/*.yaml`); this module owns only scoring + scope
6-
iteration. The decode->exec taint chain and production-tuned weights are NOT here (held back upstream)."""
5+
iteration."""
76
from .facts import build_facts
87
from .models import FiredRule, TriageResult
98
from .rules import evaluate

pydiffwatch/facts.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
primitive categories, encoded-blob signal, syntax-error, location weight; plus normalized binary/dep
33
findings and the maintainer-change flag. Pure and deterministic. Static AST analysis only — no execution.
44
5-
The import-binding machinery (_build_import_table / _resolve_call / _PRIM_BINDINGS) is the PUBLIC half of
6-
main DiffWatch's triage: a call counts as a dangerous primitive only when its receiver resolves via the
7-
file's import table to an origin in the name's allowlist (so re.compile != exec, json.loads != decode).
8-
The private decode->exec dataflow taint chain is NOT part of this engine (held back upstream)."""
5+
The import-binding machinery (_build_import_table / _resolve_call / _PRIM_BINDINGS) is what makes primitive
6+
detection precise: a call counts as a dangerous primitive only when its receiver resolves via the
7+
file's import table to an origin in the name's allowlist (so re.compile != exec, json.loads != decode)."""
98
import ast
109
import math
1110
import posixpath

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "Rules-driven PyPI supply-chain malware scanner (open-source PyDif
55
readme = "README.md"
66
requires-python = ">=3.11"
77
license = { text = "MIT" }
8-
authors = [{ name = "Ankit Prateek" }]
8+
authors = [{ name = "Appy" }]
99
dependencies = ["PyYAML>=6.0"]
1010

1111
[project.optional-dependencies]

rules/community/combos.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Co-occurring import-bound primitive categories in the same changed file. Loose combos (no dataflow):
2-
# the precise decode->exec taint chain ("obfuscated-loader") is NOT shipped here (held back upstream).
1+
# Co-occurring import-bound primitive categories in the same changed file. Loose combos (no dataflow
2+
# taint tracking): a decode and an exec in the same file score, without proving the bytes flow between them.
33
- id: combo-fetch-exec
44
description: A network fetch and an exec/eval co-occur (download-and-run a second stage).
55
applies_to: code

0 commit comments

Comments
 (0)