This document defines the mandatory integration requirements for all rules compilers to ensure consistent security validation across the codebase.
All compilers must pass integration tests that verify they're using the validation library:
# .github/workflows/validation-compliance.yml
name: Validation Compliance
on: [push, pull_request]
jobs:
typescript-compliance:
runs-on: ubuntu-latest
steps:
- name: Check TypeScript uses validation library
run: |
cd src/rules-compiler-typescript
# Verify WASM module is imported
grep -q "adguard_validation" package.json || exit 1
grep -q "validate_local_file\|validate_remote_url" src/**/*.ts || exit 1
dotnet-compliance:
runs-on: ubuntu-latest
steps:
- name: Check .NET uses validation library
run: |
cd src/rules-compiler-dotnet
# Verify native library is referenced
grep -q "adguard_validation" src/**/*.csproj || exit 1
grep -rq "ValidationLibrary\|P/Invoke" src/ || exit 1
# Similar checks for Python and Rust compilersEach compiler must implement a --validate-integration flag that verifies the validation library is properly integrated:
# All compilers must support this
npm run compile -- --validate-integration
dotnet run --project RulesCompiler.Console -- --validate-integration
rules-compiler --validate-integration
cargo run --release -- --validate-integrationThis flag should:
- Attempt to load the validation library
- Run a simple validation test
- Exit with code 0 if successful, 1 if failed
All compilers must call validation library functions at these points:
Before Compilation:
// TypeScript example (all compilers must have equivalent)
import { Validator, ValidationConfig, VerificationMode } from '@adguard/validation';
async function compile(config: CompilerConfig): Promise<CompilerResult> {
const validator = new Validator(ValidationConfig.default());
// 1. MANDATORY: Validate all local input files
for (const localFile of getLocalInputFiles()) {
const result = await validator.validate_local_file(localFile);
if (!result.is_valid) {
throw new CompilationError(`Invalid input file: ${localFile}`);
}
}
// 2. MANDATORY: Validate all remote URLs
for (const url of getRemoteUrls()) {
const result = await validator.validate_remote_url(url, getExpectedHash(url));
if (!result.is_valid) {
throw new CompilationError(`Invalid remote URL: ${url}`);
}
}
// 3. Proceed with compilation using @jk-com/adblock-compiler
const output = await hostlistCompiler.compile(config);
// 4. MANDATORY: Handle file conflicts
const finalPath = await resolveConflict(output.path, config.conflictStrategy);
// 5. MANDATORY: Create archive if enabled
if (config.archiving.enabled) {
await createArchive(inputDir, archiveDir, output.hash, output.ruleCount);
}
return output;
}Each compiler must have integration tests that verify:
// Test that compilation fails if local file has invalid syntax
test('rejects invalid local file', async () => {
const invalidFile = 'test-data/invalid-syntax.txt';
await expect(compile(configWithFile(invalidFile))).rejects.toThrow();
});// Test that compilation detects tampered files
test('detects file tampering via hash', async () => {
// First compile creates hash
await compile(config);
// Modify file
modifyFile('data/input/rules.txt');
// Second compile should detect tampering
await expect(compile(configWithStrictMode)).rejects.toThrow(/hash mismatch/i);
});// Test that HTTP URLs are rejected
test('rejects insecure HTTP URLs', async () => {
const httpUrl = 'http://insecure.example.com/list.txt';
await expect(compile(configWithUrl(httpUrl))).rejects.toThrow(/HTTPS/i);
});// Test that archives are created when enabled
test('creates archive when enabled', async () => {
const config = { ...baseConfig, archiving: { enabled: true } };
await compile(config);
expect(fs.existsSync('data/archive')).toBe(true);
const archives = fs.readdirSync('data/archive');
expect(archives.length).toBeGreaterThan(0);
});All compilers must validate that configuration includes validation settings:
function validateConfig(config: CompilerConfig): void {
// MANDATORY: hashVerification section must exist
if (!config.hashVerification) {
throw new Error('Missing hashVerification configuration');
}
// MANDATORY: Must specify verification mode
if (!['strict', 'warning', 'disabled'].includes(config.hashVerification.mode)) {
throw new Error('Invalid hashVerification.mode');
}
// Additional validation...
}Each compiler's dependency file must declare the validation library:
TypeScript (package.json):
{
"dependencies": {
"@adguard/validation": "file:../adguard-validation/pkg"
}
}.NET (csproj):
<ItemGroup>
<NativeLibraryReference Include="adguard_validation" />
</ItemGroup>Python (requirements.txt):
adguard-validation>=1.0.0
Rust (Cargo.toml):
[dependencies]
adguard-validation = { path = "../adguard-validation/adguard-validation-core" }A pre-commit hook verifies validation library integration:
#!/bin/bash
# .git/hooks/pre-commit
echo "Checking validation library integration..."
# Check TypeScript
if ! grep -q "adguard_validation" src/rules-compiler-typescript/package.json; then
echo "ERROR: TypeScript compiler missing validation library dependency"
exit 1
fi
# Check .NET
if ! grep -q "adguard_validation" src/rules-compiler-dotnet/src/**/*.csproj; then
echo "ERROR: .NET compiler missing validation library reference"
exit 1
fi
# Similar checks for Python and Rust
echo "✓ All compilers properly integrated with validation library"Each compiler's README must include:
- Integration Status section showing validation library usage
- Security Features section listing which validations are performed
- Configuration section documenting validation settings
- Code examples showing validation in action
PR template includes validation library checklist:
## Validation Library Integration
- [ ] Uses validation library for file validation
- [ ] Uses validation library for URL security
- [ ] Implements hash verification
- [ ] Creates archives when enabled
- [ ] Handles file conflicts
- [ ] Integration tests pass
- [ ] Documentation updatedAny PR that bypasses the validation library is automatically rejected.
Exceptions require:
- Written justification
- Security team approval
- Alternative security measures documented
- Temporary exemption with deadline
Maintainers can verify compliance with:
# Run compliance check across all compilers
./tools/check-validation-compliance.sh
# Expected output:
# ✓ TypeScript: Validation library integrated
# ✓ .NET: Validation library integrated
# ✓ Python: Validation library integrated
# ✓ Rust: Validation library integrated
# ✓ All integration tests passing- CI fails - PR cannot be merged
- Code review rejection - Automatic "Request Changes"
- Security alert - Flagged in security dashboard
- Rollback - Non-compliant code reverted if merged
- Phase 1 (Current): Validation library created, documented
- Phase 2 (Next): Integrate into TypeScript compiler (reference implementation)
- Phase 3: Integrate into .NET, Python, Rust compilers
- Phase 4: Enable CI enforcement (warnings only)
- Phase 5: Enable CI enforcement (blocking)
- Phase 6: Remove legacy validation code
Questions about integration? See:
src/adguard-validation/README.md- Full integration guidedocs/validation-integration-guide.md- Step-by-step tutorial- GitHub Discussions - Ask the community