Skip to content

Commit bc8fd83

Browse files
committed
feat: harden signal analysis with research-informed review
1 parent 7835d7a commit bc8fd83

34 files changed

Lines changed: 1326 additions & 146 deletions

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
All notable user-facing changes to Signal Sieve are recorded here.
44

5+
## Unreleased
6+
7+
- Hardened community verdict parsing and distinguished HTTP, authentication
8+
and rewrite-configuration errors from connection failures.
9+
- Added explicit rewrite consent, native post-analysis and integrity checks
10+
before accepting a community-engine clean copy.
11+
- Exposed hidden display controls in bounded external-result previews.
12+
- Added bounded local regularity windows and repeated-context diagnostics,
13+
with research sources and evidence limits in `RESEARCH_BASIS.md`.
14+
- Rejected oversized surface-probe input and nonfinite display values.
15+
- Improved defensive handling of obfuscated scam text, ambiguous URL wrappers,
16+
byte-preserving URL queries, malformed ZIP records and child-process failures.
17+
518
## 0.13.0 — 2026-08-25
619

720
- Made automatic Input processing honor the user's selected Safe Clean,

COMMUNITY_ENGINES.md

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ project's optional heavyweight harnesses implicitly.
2525
This is composition, not code ownership: the external project is neither
2626
forked nor copied into the Signal Sieve source tree.
2727

28-
## Start the compatible service
28+
## Start the service (inspection first)
2929

3030
Review the upstream source and release notes first. The shortest upstream
3131
installation uses Python 3.10 or newer:
@@ -52,11 +52,44 @@ replace it with a reviewed release tag and update deliberately. Signal Sieve
5252
does not run `git pull`, `docker pull`, package installation, or a shell command
5353
on the user's behalf.
5454

55-
In Signal Sieve, paste text, choose **Community Engines**, confirm that the
56-
local service is ready, and then choose **Inspect with Engine** or **Create
57-
Community Clean Copy**. The latter does not replace Input or the clipboard. It
58-
shows the engine report, performs a native residual-risk analysis, and requires
59-
**Use as Result**.
55+
These commands start the service; they do **not** establish text rewrite
56+
readiness. In Signal Sieve, paste text, choose **Community Engines**, check the
57+
connection and choose **Inspect with Engine**. **Capabilities** works even
58+
without Input. Connection health is not a detector or rewrite readiness test.
59+
60+
### Text cleaning requires Layer B configuration
61+
62+
The current upstream text `/clean` route requires a Layer B rewrite strategy
63+
and its model/backend dependencies. A bare Python service or core image may
64+
answer health/inspect while rejecting clean. Follow the reviewed version's
65+
[upstream configuration guide](https://github.com/guillaumemeyer/watermarks-remover#configuration-env-vars-for-docker-compose)
66+
and configure its strategy/backend before trying **Create Community Clean Copy**.
67+
Signal Sieve does not install a model or silently select a remote provider.
68+
69+
Review that configuration and acknowledge the rewrite/data-handling warning in
70+
the panel. The backend may change meaning, download models or send content to
71+
another service. Numeric loopback restricts Signal Sieve's destination, **not**
72+
the external engine's subsequent network activity. Use synthetic text first.
73+
74+
Cleaning does not replace Input or the clipboard. The panel previews the
75+
candidate and runs all deterministic native text checks (Unicode/covert
76+
channels, Code Guard, binary content, URLs including private rules, UUIDs and
77+
scam signals), plus rewrite integrity. **Use as Result** is blocked when any
78+
native finding remains, analysis is incomplete, protected numbers/URLs/quotes
79+
change, source code is involved, or Input no longer matches the reviewed bytes.
80+
This conservative gate is not proof of semantic equivalence: always read the
81+
candidate. No personal pattern history is read or learned from this review.
82+
83+
### Troubleshooting
84+
85+
| Message | Meaning / next step |
86+
| --- | --- |
87+
| No service answered | Start your reviewed engine on `127.0.0.1:8765`. |
88+
| Rewrite configuration required | Inspect can work; configure upstream Layer B before Clean. |
89+
| Authentication required | This adapter does not yet support the engine's API key mode. |
90+
| HTTP rejection / engine error | The server answered but rejected the request; inspect its bounded error. |
91+
| Unknown verdict | The response supplied no supported verdict; it is not shown as green. |
92+
| Invalid response | Malformed or contradictory evidence was rejected. |
6093

6194
Developers can verify the complete adapter against a running compatible service
6295
with a synthetic hidden-Unicode fixture:
@@ -65,10 +98,16 @@ with a synthetic hidden-Unicode fixture:
6598
./community-engine-smoke-test.sh
6699
```
67100

68-
The smoke test exercises health, capabilities, inspect, clean, and Signal
101+
With a configured rewrite backend, the smoke test exercises health, capabilities, inspect, clean, and Signal
69102
Sieve's native residual-risk analysis. It fails closed and never uses clipboard
70103
contents.
71104

105+
For a deliberately unconfigured Layer B service, run
106+
`./community-engine-smoke-test.sh --expect-rewrite-unconfigured`. This separately
107+
checks health, capabilities, the suspicious inspection verdict and the explicit
108+
configuration error. It does **not** certify cleaning or substitute for the full
109+
smoke test above.
110+
72111
### Manual GitHub compatibility run
73112

74113
Maintainers can open **Actions → Community Engine Compatibility → Run
@@ -101,7 +140,9 @@ log for seven days and receives only read access to this repository.
101140

102141
## Result semantics
103142

104-
An external report proves only what its named detector and configuration can
143+
The adapter supports legacy Boolean and structured `suspicious.verdict`
144+
responses. Missing/null verdicts remain unknown; invalid or contradictory
145+
structured evidence fails closed. An external report proves only what its named detector and configuration can
105146
support. A result is not proof of authorship, AI generation, provider identity,
106147
or malicious intent. Provider-keyed and learned watermarks remain untestable
107148
unless the matching detector, keys or validation material, tokenizer, and

FORMAT_SECURITY.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ structures, writes a new file, reopens it, reanalyzes it, and confirms the
55
source remained byte-for-byte unchanged. Unknown, malformed, signed, encrypted,
66
or ambiguously linked structures fail closed.
77

8+
ZIP-based documents validate every local header against its central record
9+
before inspection or rebuilding, including entries scheduled for removal.
10+
Names, flags, methods, CRC/size declarations and streaming descriptors must
11+
agree; local ranges cannot overlap or enter the central directory. Split-disk
12+
counts, symlink entries, traversal/alias paths and malformed UTF-8 names marked
13+
as UTF-8 are refused. Both signed and unsigned 32-bit streaming descriptors are
14+
supported. This conservative policy follows the record structures in the
15+
[PKWARE ZIP specification](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT).
16+
Structural agreement does not prove the document body is benign.
17+
818
| Format | Structural inspection | Conservative cleaning |
919
| --- | --- | --- |
1020
| WebP | RIFF `C2PA`, `EXIF`, `XMP ` chunks | Rebuild RIFF, clear EXIF/XMP VP8X flags, preserve image/animation/ICC chunks |

PIXEL_MODULES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ the contract to preserve the same staging and verification boundary.
1616

1717
## Module folder
1818

19+
Runtime arguments must be finite and greater than zero, up to 300 seconds.
20+
The bridge uses monotonic deadlines, discards stderr, bounds response reads,
21+
and forcibly stops the directly launched process on deadline or output-budget
22+
violations. This includes a module that ignores SIGTERM. Supervision is not an
23+
OS sandbox, a hard disk quota, or containment of a module's descendants.
24+
1925
The selected folder must contain `signalsieve-pixel-module.json` and a regular,
2026
non-symlink executable below that same folder. Manifest schema version 1 is:
2127

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,17 @@ they contain no real account, organization, or third-party message data.
299299
address `127.0.0.1:8765`. The app supports its documented health,
300300
capabilities, text inspection, and clean-copy routes; it never downloads,
301301
launches, or updates the external project. Cleaned text is reanalyzed by
302-
Signal Sieve before the user may place it in Result. Signal Sieve remains
302+
Signal Sieve, including native risk checks and rewrite integrity, before the
303+
user may place it in Result. Current upstream text cleaning requires a
304+
configured Layer B rewrite backend; a healthy connection alone is not enough.
305+
Missing verdicts remain unknown, never green. Signal Sieve remains
303306
fully usable without the service. Setup, update, licensing, and trust details
304307
are in [COMMUNITY_ENGINES.md](COMMUNITY_ENGINES.md).
308+
309+
Research-informed improvements include escaped community-engine previews,
310+
bounded local regularity windows and repeated-context warnings. These are
311+
defensive review aids, not provider watermark verdicts. See the three papers,
312+
implementation choices and limitations in [RESEARCH_BASIS.md](RESEARCH_BASIS.md).
305313
- **File Provenance Inspector:** performs a bounded, read-only scan for C2PA
306314
container markers and common EXIF/XMP or document metadata in PNG, JPEG,
307315
WebP, AVIF, HEIC/HEIF, BMP, GIF, TIFF, SVG, PDF, DOCX, XLSX, PPTX, EPUB, ODT,

RESEARCH_BASIS.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Research-informed signal hardening
2+
3+
This note connects three scientific papers to specific Signal Sieve changes.
4+
These are defensive engineering adaptations, not reproductions of the papers'
5+
benchmarks or claims of a universal watermark detector. All examples are
6+
synthetic and native analysis stays offline.
7+
8+
## 1. Invisible text and misleading displays
9+
10+
**Boucher et al., _Bad Characters: Imperceptible NLP Attacks_ (IEEE S&P 2022).**
11+
[Paper](https://arxiv.org/abs/2106.09898)
12+
13+
The paper studies invisible characters, homoglyphs, reordering and deletion
14+
controls that can cause differences between displayed and processed text.
15+
16+
**Engineering application:** community reports, errors and candidate previews
17+
now expose invisible/control scalars as `⟦U+XXXX⟧`. This includes backspace,
18+
delete, escape and carriage return rather than interpreting their display
19+
effects. Previews are bounded to 8,000 scalars and visibly indicate truncation;
20+
analysis and explicit candidate acceptance continue to use the original bytes.
21+
Ordinary Arabic/Hebrew letters, newlines and tabs are preserved in previews.
22+
23+
This is a display safeguard, not a complete Unicode confusable detector or
24+
proof that a flagged character was inserted maliciously. Context-sensitive
25+
emoji/script cleaning policy is unchanged.
26+
27+
## 2. Do not hide local signals inside document averages
28+
29+
**Kirchenbauer et al., _On the Reliability of Watermarks for Large Language
30+
Models_ (ICLR 2024).** [Paper](https://arxiv.org/abs/2306.04634)
31+
32+
The paper examines edited and mixed-origin documents. Its WinMax detector
33+
uses keyed token evidence over spans and requires false-positive calibration
34+
for the multiple-window search.
35+
36+
**Engineering application:** Surface Regularity now examines overlapping
37+
180-word windows, normally 90 words apart, and shows up to three non-overlapping
38+
repetitive regions by word offset. It uses existing repetition/diversity
39+
features. At most 256 windows are examined; longer documents use evenly spaced
40+
starts including the first and last, with an explicit sampled-coverage notice.
41+
42+
This is **not WinMax**: there are no keyed green-list hits, z-tests or calibrated
43+
p-values. Local maxima never increase the document's global heuristic score.
44+
A highlighted region is a review clue; no highlight does not establish absence
45+
of a watermark. Word offsets refer to the app's lexical segmentation.
46+
47+
## 3. Repeated text is not independent evidence
48+
49+
**Dathathri et al., _Scalable watermarking for identifying large language model
50+
outputs_ (Nature 2024).**
51+
[Paper](https://www.nature.com/articles/s41586-024-08025-4)
52+
53+
SynthID-Text uses keyed context-dependent sampling and scoring; the paper also
54+
describes repeated-context masking. Its measurement conditions cannot be
55+
replaced by word count or surface regularity alone.
56+
57+
**Engineering application:** the probe reports distinct four-word contexts
58+
against all four-word context positions. Below 50% distinct contexts it warns
59+
that repetition dominates the sample. This 50% threshold is a product heuristic,
60+
not a threshold from the paper or a calibrated estimate of effective sample
61+
size. Duplicating a paragraph increases length without manufacturing new
62+
contextual diversity. Words here are not the provider's model tokens.
63+
64+
No SynthID key, tokenizer, detector model, or vendor attribution is supplied by
65+
this change. Short or repetitive human writing is not labelled AI-generated.
66+
67+
## Defensive validation
68+
69+
`ResearchSignalHardeningTests.swift` covers display controls and bounded
70+
previews, a repetitive island inside a diverse document, duplicated contexts,
71+
sampled-window coverage, oversized input and nonfinite display values.
72+
`CommunityCleanReviewTests.swift` and `CommunityWatermarkServiceTests.swift`
73+
cover the separate community-adapter trust boundary and acceptance checks.
74+
75+
The probe refuses input above the shared 1 MiB UTF-8 budget before analysis.
76+
Statistical signals remain separate from exact Unicode findings. Future
77+
provider detection needs independently reviewed keys/configuration, appropriate
78+
negative controls, language/domain coverage and measured false-positive rates.
79+
80+
### Validation record — 2026-09-06
81+
82+
- 321 Swift tests passed, including 27 focused community/probe/research tests.
83+
- All 47 native test groups passed, including Apple Vision OCR.
84+
- The development quality gate passed packaging, warnings, privacy checks,
85+
linkage and ad-hoc signature verification. This is not notarization.
86+
- Real upstream adapter preflight passed against
87+
[`d9e9590d94e19b39eb2794266292324bfec8249a`](https://github.com/guillaumemeyer/watermarks-remover/commit/d9e9590d94e19b39eb2794266292324bfec8249a):
88+
health, capabilities, structured suspicious verdict and HTTP 400 missing-
89+
rewrite configuration. The service was bound to loopback, used synthetic
90+
text and was stopped after the check. No rewrite model was downloaded.
91+
- A real configured Layer B clean output was **not** tested in this pass.
92+
The preflight explicitly reports that limitation; it is not a watermark
93+
removal benchmark or an end-to-end rewrite certificate.

SECURITY.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ public issue. Provide the smallest synthetic reproduction possible.
1010

1111
## Security boundaries
1212

13+
The [September defensive audit](docs/DEFENSIVE_AUDIT_2026-09-06.md) documents
14+
reproduced bypasses, corrections, regression coverage, and remaining limits.
15+
Scam analysis inspects overlapping 64,000-character windows throughout the
16+
input and retains the strongest window's bounded evidence. It does not combine
17+
unrelated distant phrases into a synthetic threat. Compatibility normalization
18+
and default-ignorable removal are comparison-only operations on brand words;
19+
the original copied text is preserved. These signals are heuristic review aids.
20+
21+
External text and pixel modules require finite positive timeouts, use monotonic
22+
deadlines, discard stderr, and bound retained response bytes. Deadline or output
23+
violations forcibly stop the directly launched process with a bounded wait.
24+
PDF, Ollama, and Community Engine failure paths use the same bounded stop.
25+
This is process supervision, not a sandbox or a resource quota on descendants.
26+
1327
- Text processing, Code Guard, Binary Guard, Vaccine, and OCR are local.
1428
- Surface Regularity is a local, deterministic stylometric triage screen. Its score is not a
1529
probability and must never be presented as confirmation of AI generation,

Sources/SignalSieve/App/ContentView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ struct ContentView: View {
137137
CommunityEnginesView(
138138
text: model.input,
139139
language: model.language,
140+
customRules: model.privateRules,
140141
onUseResult: { model.output = $0 }
141142
)
142143
}

0 commit comments

Comments
 (0)