tests/test_hygiene.py — Hidden Character Scanner
From version 0.1.1 of Hidden Character Scanner, shown publicly by its creator. 6.9 KiB · SHA-256 46fb87dfb8ff38d4cf432811bdeb1bdf9db0ce070f1a2b0bc0bd661ad814c23a.
# By Zero Width Lab (zerowidthlab.com)
"""Check publication hygiene without embedding hidden text."""
from __future__ import annotations
import argparse
import ast
import json
import re
import sys
import unicodedata
import unittest
from pathlib import Path
__author__ = "Zero Width Lab"
SIGNATURE = "By Zero Width Lab (zerowidthlab.com)"
ROOT = Path(__file__).resolve().parent.parent
TEXT_SUFFIXES = {".py", ".md", ".json", ".txt"}
INVISIBLE_RANGES = (
(0x00A0, 0x00A0), (0x061C, 0x061C), (0x2000, 0x200F),
(0x202A, 0x202F), (0x205F, 0x2069), (0x3000, 0x3000),
(0xFE00, 0xFE0F), (0xFEFF, 0xFEFF),
(0xE0000, 0xE007F), (0xE0100, 0xE01EF),
)
AI_NAMES = tuple(left + right for left, right in (
("Open", "AI"), ("Anth", "ropic"), ("Chat", "G" + "PT"),
("Gem", "ini"), ("Clau", "de"), ("Co", "dex"),
("Co", "pilot"), ("Son", "net"), ("Op", "us"),
))
AI_PHRASES = ("generated" + " by", "written" + " by")
GPT_TOKEN = "G" + "PT"
def invisible_character(character: str) -> bool:
point = ord(character)
return (unicodedata.category(character) == "Cf"
or any(start <= point <= end for start, end in INVISIBLE_RANGES))
def ai_attribution(text: str) -> bool:
lowered = text.casefold()
return (any(name.casefold() in lowered for name in AI_NAMES)
or any(phrase in lowered for phrase in AI_PHRASES)
or re.search(r"\b" + GPT_TOKEN + r"\b", text) is not None)
def publication_files() -> list[Path]:
paths = []
for path in ROOT.rglob("*"):
if not path.is_file() or path.suffix.lower() not in TEXT_SUFFIXES:
continue
relative = path.relative_to(ROOT)
if any(part in {".git", "dist", "__pycache__"} for part in relative.parts):
continue
paths.append(path)
return sorted(paths)
class PublicationHygieneTests(unittest.TestCase):
def test_no_forbidden_constructs(self) -> None:
forbidden = {"eval", "exec", "compile", "__import__"}
for path in publication_files():
if path.suffix != ".py":
continue
tree = ast.parse(path.read_text(encoding="utf-8"))
for node in ast.walk(tree):
if isinstance(node, (ast.Import, ast.ImportFrom)):
modules = ([alias.name for alias in node.names] if isinstance(node, ast.Import)
else [node.module or ""])
self.assertFalse(any(name.split(".")[0] in {"pickle", "ctypes"}
for name in modules), str(path))
if not isinstance(node, ast.Call):
continue
name = (node.func.id if isinstance(node.func, ast.Name)
else node.func.attr if isinstance(node.func, ast.Attribute) else "")
self.assertNotIn(name, forbidden, str(path))
self.assertNotEqual(name, "system", str(path))
for keyword in node.keywords:
if keyword.arg == "shell":
self.assertIsInstance(keyword.value, ast.Constant, str(path))
self.assertIs(keyword.value.value, False, str(path))
def test_no_invisible_or_zero_width_characters(self) -> None:
for path in publication_files():
contents = path.read_text(encoding="utf-8")
for character in contents:
point = ord(character)
if invisible_character(character):
self.fail(f"invisible U+{point:04X} in {path.relative_to(ROOT)}")
def test_invisible_check_covers_scanner_categories(self) -> None:
points = (0x00AD, 0x00A0, 0x061C, 0x2000, 0x200A, 0x200B,
0x202E, 0x202F, 0x205F, 0x2060, 0x2068, 0x3000,
0xFE0F, 0xFEFF, 0xE0001, 0xE0100)
for point in points:
with self.subTest(point=point):
self.assertTrue(invisible_character(chr(point)))
def test_no_private_identifiers(self) -> None:
guid_pattern = r"\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b"
email_pattern = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b"
home_pattern = r"/(?:Users|home)/[^/\s]+/"
tenant_pattern = r"[A-Za-z0-9-]+\.(?:onmicrosoft|sharepoint)\.com\b"
for path in publication_files():
contents = path.read_text(encoding="utf-8")
for pattern in (guid_pattern, email_pattern, home_pattern, tenant_pattern):
self.assertIsNone(re.search(pattern, contents), str(path.relative_to(ROOT)))
self.assertFalse(ai_attribution(contents), str(path.relative_to(ROOT)))
def test_ai_attribution_check(self) -> None:
for name in (*AI_NAMES, GPT_TOKEN, *AI_PHRASES):
with self.subTest(name=name):
self.assertTrue(ai_attribution(name))
self.assertFalse(ai_attribution("agptx and ordinary text"))
self.assertFalse(ai_attribution("gpt"))
def test_signatures_and_python_authorship(self) -> None:
for path in publication_files():
contents = path.read_text(encoding="utf-8")
if path.suffix == ".md":
self.assertEqual(contents.splitlines()[-1], SIGNATURE, str(path.relative_to(ROOT)))
if path.suffix == ".py":
self.assertIn("# " + SIGNATURE, contents.splitlines()[:5], str(path.relative_to(ROOT)))
self.assertIn('__author__ = "Zero Width Lab"', contents, str(path.relative_to(ROOT)))
def test_full_package_lists_every_shipped_file(self) -> None:
shipped = {str(path.relative_to(ROOT)) for path in publication_files()
if "packaging" not in path.relative_to(ROOT).parts}
self.assertIn("LICENSE.txt", shipped)
spec_path = ROOT / "packaging" / "package-spec.json"
if spec_path.exists():
specification = json.loads(spec_path.read_text(encoding="utf-8"))
declared = {entry["path"] for entry in specification["files"]}
self.assertEqual(declared, shipped)
for entry in specification["files"]:
self.assertFalse(any(part.startswith("_") for part in Path(entry["path"]).parts))
if entry["path"].endswith(".py"):
self.assertTrue(entry["executable"], entry["path"])
def test_source_package_root_keys(self) -> None:
descriptor = json.loads((ROOT / "source-package.json").read_text(encoding="utf-8"))
self.assertEqual(set(descriptor), {"schema_version", "runtimes", "dependencies", "operations",
"authorization", "network", "safety", "tests"})
self.assertEqual(descriptor["network"]["domains"], [])
def main() -> None:
parser = argparse.ArgumentParser(description="Run Hidden Character Scanner hygiene checks.", epilog=SIGNATURE)
_, remaining = parser.parse_known_args()
unittest.main(argv=[sys.argv[0], *remaining])
if __name__ == "__main__":
main()
License: MIT (read it).
MIT
MIT LicenseCopyright (c) 2026 Zero Width Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.