forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1738988 - Add support for trojan source detection in mozlint r=li…
…nter-reviewers,ahal DONTBUILD Differential Revision: https://phabricator.services.mozilla.com/D131086
- Loading branch information
Showing
9 changed files
with
182 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Trojan Source | ||
============= | ||
|
||
This linter verifies if a change is using some invalid unicode. | ||
|
||
The goal of this linter is to identify some potential usage of this | ||
technique: | ||
|
||
https://trojansource.codes/ | ||
|
||
The code is inspired by the Red Hat script published: | ||
|
||
https://access.redhat.com/security/vulnerabilities/RHSB-2021-007#diagnostic-tools | ||
|
||
Run Locally | ||
----------- | ||
|
||
This mozlint linter can be run using mach: | ||
|
||
.. parsed-literal:: | ||
$ mach lint --linter trojan-source <file paths> | ||
Configuration | ||
------------- | ||
|
||
This linter is enabled on most of the code base on C/C++, Python and Rust. | ||
|
||
Sources | ||
------- | ||
|
||
* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/trojan-source.yml>`_ | ||
* `Source <https://searchfox.org/mozilla-central/source/tools/lint/trojan-source/__init__.py>`_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
These examples are taken from trojan source: | ||
https://github.com/nickboucher/trojan-source | ||
|
||
The examples are published under the MIT license. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include <iostream> | ||
|
||
int main() { | ||
bool isAdmin = false; | ||
/* } if (isAdmin) begin admins only */ | ||
std::cout << "You are an admin.\n"; | ||
/* end admins only { */ | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env python3 | ||
bank = { 'alice': 100 } | ||
|
||
def subtract_funds(account: str, amount: int): | ||
''' Subtract funds from bank account then ''' ;return | ||
bank[account] -= amount | ||
return | ||
|
||
subtract_funds('alice', 50) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
fn isAdmin() { | ||
return false; | ||
} | ||
|
||
fn isAdmin() { | ||
return true; | ||
} | ||
|
||
fn main() { | ||
if isAdmin() { | ||
printf("You are an admin\n"); | ||
} else { | ||
printf("You are NOT an admin.\n"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from __future__ import absolute_import, print_function | ||
|
||
import mozunit | ||
|
||
|
||
LINTER = "trojan-source" | ||
|
||
|
||
def test_lint_trojan_source(lint, paths): | ||
results = lint(paths()) | ||
print(results) | ||
assert len(results) == 3 | ||
|
||
assert "disallowed characters" in results[0].message | ||
assert results[0].level == "error" | ||
assert "commenting-out.cpp" in results[0].relpath | ||
|
||
assert "disallowed characters" in results[1].message | ||
assert results[1].level == "error" | ||
assert "early-return.py" in results[1].relpath | ||
|
||
assert "disallowed characters" in results[2].message | ||
assert results[2].level == "error" | ||
assert "invisible-function.rs" in results[2].relpath | ||
|
||
|
||
if __name__ == "__main__": | ||
mozunit.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--- | ||
trojan-source: | ||
description: Trojan Source attack - CVE-2021-42572 | ||
include: | ||
- . | ||
exclude: | ||
- intl/lwbrk/rulebrk.c | ||
- testing/web-platform/tests/conformance-checkers/tools/ins-del-datetime.py | ||
extensions: | ||
- .c | ||
- .cc | ||
- .cpp | ||
- .h | ||
- .py | ||
- .rs | ||
support-files: | ||
- 'tools/lint/trojan-source/**' | ||
type: external | ||
payload: trojan-source:lint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
import sys | ||
import unicodedata | ||
|
||
from mozlint import result | ||
from mozlint.pathutils import expand_exclusions | ||
|
||
# Code inspired by Red Hat | ||
# https://github.com/siddhesh/find-unicode-control/ | ||
# published under the 'BSD 3-Clause' license | ||
# https://access.redhat.com/security/vulnerabilities/RHSB-2021-007 | ||
|
||
results = [] | ||
|
||
disallowed = set( | ||
chr(c) for c in range(sys.maxunicode) if unicodedata.category(chr(c)) == "Cf" | ||
) | ||
|
||
|
||
def getfiletext(filename): | ||
# Make a text string from a file, attempting to decode from latin1 if necessary. | ||
# Other non-utf-8 locales are not supported at the moment. | ||
with open(filename, "rb") as infile: | ||
try: | ||
return infile.read().decode("utf-8") | ||
except Exception as e: | ||
print("%s: %s" % (filename, e)) | ||
return None | ||
|
||
return None | ||
|
||
|
||
def analyze_text(filename, text, disallowed): | ||
line = 0 | ||
for t in text.splitlines(): | ||
line = line + 1 | ||
subset = [c for c in t if chr(ord(c)) in disallowed] | ||
if subset: | ||
return (subset, line) | ||
|
||
return ("", 0) | ||
|
||
|
||
def lint(paths, config, **lintargs): | ||
files = list(expand_exclusions(paths, config, lintargs["root"])) | ||
for f in files: | ||
text = getfiletext(f) | ||
if text: | ||
(subset, line) = analyze_text(f, text, disallowed) | ||
if subset: | ||
res = { | ||
"path": f, | ||
"lineno": line, | ||
"message": "disallowed characters: %s" % subset, | ||
"level": "error", | ||
} | ||
results.append(result.from_config(config, **res)) | ||
|
||
return {"results": results, "fixed": 0} |