StegoGuard

StegoGuard (ODC)

Stable version 0.1.1 (Compatible with ODC)
Uploaded on 31 Jul by Alexandre Realinho
StegoGuard

StegoGuard (ODC)

Documentation
0.1.1

STEP-BY-STEP INSTRUCTIONS - StegoGuard
=========================================


PART 1 - INSTALLATION
---------------------

Step 1. Open your ODC application or library in ODC Studio.

Step 2. Click the Dependencies icon (puzzle piece) in the top toolbar.

Step 3. In the search box, type "StegoGuard" and select it from the
results.

Step 4. Tick the following in the dependency picker:
- The Server Action "RecompressImage"
- The Structure "StegoGuardResult"
- The Structure "StegoAuditResult"

Step 5. Click "Apply" to add the dependency to your module.

Step 6. Publish the module. StegoGuard is now available under the
Logic tab of your module.


PART 2 - FIRST CALL (MINIMAL EXAMPLE)
--------------------------------------

Step 1. Create or open a Server Action where you want to disrupt an
uploaded image (for example, immediately after receiving a
File Upload widget's content).

Step 2. Drag StegoGuard.RecompressImage from the Logic tab onto the
canvas.

Step 3. Wire the four input parameters:
- RawImage -> the Binary Data of the uploaded image
- Quality -> 85 (recommended default)
- OutputFormat -> "" (empty string preserves input format)
- Sigma -> 0.5 (recommended default)

Step 4. Use the output field RecompressImage.CleanImage in place of
the original bytes for every downstream call (AI API,
storage, database).

That is the minimum required. All other features are optional.


PART 3 - RECOMMENDED FULL PIPELINE
-----------------------------------

For defence in depth, run StegoGuard as the second stage of a
three-stage chain:

Uploaded image
|
v
Stage 1 - FileMetadataStrip.StripFileMetadata
Removes EXIF, IPTC, XMP, and container metadata.
|
v
Stage 2 - StegoGuard.RecompressImage
Disrupts pixel-level, DCT, and alpha-channel stego via
a lossy JPEG round-trip. Optional Gaussian blur adds
spatial smoothing.
|
v
Stage 3 - QRGuard (if you handle QR-carrying images)
Screens QR-code prompt-injection payloads that survive
JPEG recompression (Reed-Solomon error correction).
|
v
Vision-capable AI model (or storage / database)

If you only need Stage 2, that is fine - StegoGuard is standalone
and does not require the other components.


PART 4 - CONFIGURATION
----------------------

RecompressImage takes four inputs. Only RawImage is mandatory; the
other three have safe defaults but can be tuned per scenario.


Quality (Integer, 1 to 100)
---------------------------
Controls the JPEG quality used during recompression. Lower values
disrupt payloads more aggressively but reduce visual fidelity.

85 Recommended default. Balanced disruption and quality.
75 Stronger disruption for high-security uploads.
100 Minimum disruption (still runs the round-trip).
0 Treated as 85. Values above 100 clamped to 100.

Applies to every output format, including lossless targets like PNG
- it still controls the intermediate JPEG encode that drives the
disruption.


OutputFormat (Text)
-------------------
Controls the container format of the output image. Case-insensitive.

"" (empty) Preserve the input format (default).
"JPEG" (or JPG) Force JPEG output. Strongest disruption; alpha
flattened to white.
"PNG" Force PNG output. Preserves transparency.

Any unrecognised value falls back to preserving the input format.


Sigma (Decimal)
---------------
Gaussian blur sigma applied after the JPEG round-trip. Disrupts
spatial-domain payloads that survive the frequency-domain step.

0.0 Disabled (default). Skips the filter.
0.5 Recommended general use. Imperceptible softening.
1.0 High-security contexts. Slight visible softening.
1.5+ Visibly softens fine detail.

Negative values are treated as 0.


RawImage (Binary Data, mandatory)
---------------------------------
Any supported image format. Pass the Content field from a File
Upload widget or a Binary Data variable already in memory.

Recognised formats include JPEG, PNG (with alpha), GIF (animated),
BMP, TIFF (multi-frame), WebP (animated), APNG, AVIF, HEIC, JXL,
JPEG 2000, PSD, and camera RAW (DNG, CR2, NEF, ARW, ORF, PEF).
Non-image files pass through unchanged with IsPassthrough = true.


PART 5 - HANDLING THE OUTPUT
----------------------------

RecompressImage returns a StegoGuardResult structure with six fields.


CleanImage (Binary Data)
The re-encoded image with steganographic payloads disrupted.
ALWAYS use this in place of the original when calling AI APIs,
saving to storage, or writing to the database.


OriginalFormat (Text)
Format detected on input (Jpeg, Png, Gif, Bmp, Tiff, WebP, ...).
Empty when IsPassthrough is True. PSB reports as Psd (shared
magic), JPEG-2000 code streams report as Jp2.


OutputFormat (Text)
Format of the output image. Empty when IsPassthrough is True.


IsPassthrough (Boolean)
True when the input is not a recognised image (PDF, DOCX, plain
text, ...). CleanImage contains the original bytes unchanged.


ProcessingError (Text)
Non-empty on decode or encode failure. CleanImage contains the
original bytes; IsPassthrough is False. LOG this and consider
blocking the upload.


StegoAudit (StegoAuditResult)
Detection audit for the input image (see Part 6).


PART 6 - INTERPRETING THE STEGOAUDIT
------------------------------------

StegoAuditResult reports what was found in the ORIGINAL bytes before
disruption. Use it for security logging.


DetectedType (Text)
The signature that triggered detection:
"" no LSB signature detected
"RGB pixel LSB" payload in RGB channel LSBs
"Alpha-channel LSB" payload in alpha channel LSBs
"RGB + Alpha pixel LSB" both channel groups


Confidence (Decimal, 0.0 to 1.0)
Above 0.7 indicates likely LSB steganography. Noisy natural
photos can push confidence above 0.6 without any payload -
review the value before blocking automatically.


RedLsb1Fraction / GreenLsb1Fraction / BlueLsb1Fraction (Decimal)
Fraction of pixels in each RGB channel whose LSB equals 1.
Values near 0.5 are suspicious. Near 0 or 1 are clean.


AlphaLsb1Fraction (Decimal)
Same for the alpha channel. Returns -1.0 when no alpha channel.


GaussianSigmaApplied (Decimal)
Sigma actually used. 0.0 when Sigma was 0 or negative, or when
IsPassthrough is True.


PART 7 - RECOMMENDED SERVER ACTION FLOW
----------------------------------------

1. Receive the uploaded image as Binary Data.

2. If you have FileMetadataStrip installed, call
StripFileMetadata first to remove EXIF, IPTC, and XMP metadata.

3. Call RecompressImage with the values from Part 4:
Quality = 85
OutputFormat = ""
Sigma = 0.5

4. Use CleanImage for all downstream calls (AI API, storage, DB).

5. If StegoAudit.Confidence > 0.7 or DetectedType is non-empty,
write StegoAudit to your audit log.

6. If ProcessingError is non-empty, log it and either block the
upload or fall back to a safe default.

7. Optionally, forward IsPassthrough to the audit log to
distinguish passthrough files from actively disrupted images.


PART 8 - TROUBLESHOOTING
------------------------

Q. High Confidence on a normal photo.
A. Noisy natural photos can push RGB LSB fractions close to 50 %.
If all three land almost exactly at 0.500 the signature is real;
if they scatter between 0.45 and 0.55 you are seeing sensor noise.

Q. Animated WebP loses trailing frames.
A. libwebpmux native library is not bundled. Only the first frame is
disrupted; trailing frames are dropped. Convert to animated GIF
or forced JPEG output as a workaround.

Q. HEIC uploads come back as JPEG.
A. HEVC encoder is GPL-licensed and cannot be bundled. HEIC decodes
via libaom AV1 fallback and is transcoded to JPEG on write.

Q. PDF files come back untouched.
A. PDFs are returned as passthrough (IsPassthrough = True).
StegoGuard operates on pixel data; use FileMetadataStrip for
the container metadata surface.

Q. TGA / ICO / WMF / RAF uploads pass through instead of being
disrupted.
A. On the current Magick.NET-Q8-AnyCPU Windows build these formats
fall through to passthrough. See docs/format-coverage.md in the
source repository for the full list. Recompressing them requires
codec delegates not part of the standard ImageMagick redist.