Security Tools
Overview
The pipeline includes automated security tools to aid in code reviews. These tools scan for common vulnerabilities and security issues, providing feedback before code is merged.
Bandit Security Scan
Bandit is an open source security linter for Python. It scans Python code for common security issues such as hardcoded passwords, SQL injection, and insecure function calls.
Pipeline Configuration
The bandit-security-scan job runs on merge requests with the following settings:
Scans all Python files recursively
Excludes
.envand.cachedirectoriesSkips B101 (assert statements) to reduce noise
Produces
bandit-report.jsonartifactAllowed to fail (does not block merge)
Review Buddy
Review Buddy is a tool built by the SDK team to identify common security issues and Q2-specific bad practices. It also tracks cache usage, extension types, and user input throughout the code to provide additional context during code reviews.
Running It Locally
Rather than waiting for the pipeline to tell you, run everything the merge request is gated on before you push:
q2 review
That runs q2 check, q2 lint, q2 test and Review Buddy, and reports a pass or
fail for each. Each stage is the real command, run as a subprocess, and its own exit code
decides the verdict - so a stage can never drift from the command it stands for.
q2 review exits non-zero if any stage failed. Name a stage and it is handed the
terminal directly: you get exactly the output and exit code of running that command
yourself, with no summarising in between.
q2 review check # same as q2 check
q2 review lint # same as q2 lint
q2 review test # same as q2 test
Naming a single stage never downloads the Review Buddy binary, since it is not needed.
Because the summary caps each stage at 20 lines, use the single-stage form when you want the full output of whichever stage failed.
To reach the binary itself, put arguments after rb. They are forwarded untouched, the
exit code is adopted, and the working directory is left wherever you were standing, so
rb behaves as though you had the binary on your PATH:
q2 review rb -h
q2 review rb review . --scan-type full-repo
What Review Buddy Scans
The Review Buddy stage diffs against the first of develop, main or master
that exists as a local branch, so it reports on your branch rather than on the whole
repository. Override the branch with --diff-target:
q2 review --diff-target release/2.3
Keeping The Binary Current
The SDK does not pin a review_buddy version. With no binary installed, q2 review
does what q2 review rb install latest does: it works out the newest version the CDN
has and fetches that build. So a fresh machine lands on the current release without anyone
having written a version number down.
It works that out by reading
https://cdn.q2developer.com/sdk/review_buddy/releases.json. The bucket denies
directory listings, so that manifest is the index, and its newest entry is the newest
published build.
To see every version that exists:
q2 review rb versions
0.13.0
0.12.0 <-- installed
0.11.0
q2 review rb install installs one. With no argument it offers a menu, the same way
q2 upgrade picks a package version - upgrades in green, downgrades in red, the
installed build marked. Name a version to skip the menu, or latest for the newest:
q2 review rb install # pick from a menu
q2 review rb install 0.12.0 # install that version
q2 review rb install latest # install the newest published
A named version is checked against the manifest first, so a typo is reported rather than failing later as a download error.
Nothing in the SDK records a version number, so a new release needs no SDK change, and a skipped version number cannot hide the releases above it.
The build is cached under ~/.antilles/bin/review_buddy, beside a current file
recording its version, and nothing re-checks the CDN afterwards. That cached copy is used
until you ask for a new one:
q2 review rb install latest
Updating review_buddy 0.12.0 -> 0.13.0
Downloading review_buddy v0.13.0, one moment
Cached review_buddy v0.13.0 at ~/.antilles/bin/review_buddy/v0.13.0/review_buddy
The version a run picks is the first of: --rb-version, $Q2SDK_REVIEW_BUDDY_VERSION,
then whatever is installed. Delete the cache and the next run is a fresh install, which
means the latest - a recorded version whose binary is gone does not drag you back to it.
A named version is never quietly upgraded: --rb-version 0.11.0 fetches 0.11.0
whether or not something newer exists, and does not consult the pointer at all.
A few things worth knowing:
Review Buddy diffs against the first of
develop,mainormasterthat exists locally, and compares commits - so uncommitted changes are not scanned. The stage says how many files it skipped for that reason.Naming a single stage, as in
q2 review lint, needs no binary and never downloads one. Only the Review Buddy stage does.The download notices go to stderr, so redirecting stdout on a first run still captures only Review Buddy’s own output.
review --format jsonalways exits0. Readresultfrom the JSON body instead of checking the exit code.--scan-type local-diffrequires the target to exist as a local branch. If it does not, the binary crashes rather than reporting an error.Version discovery reads
review_buddy.RELEASES_URL, so no version is hardcoded in the SDK and a gap in the version history cannot truncate the result. Runq2 review rb versionsto print everything the manifest advertises.To pin a different version, pass
--rb-versionor setQ2SDK_REVIEW_BUDDY_VERSION. To run a locally compiled build, pointQ2SDK_REVIEW_BUDDY_PATHat it.
High Severity Rules
Rule |
Mitigation |
|---|---|
Requirements with known issues |
Upgrade the flagged package to a newer version that addresses the known issues. |
Minimum SDK version check |
Upgrade q2-sdk version >= 2.257.0 in requirements.txt. |
SQL files |
All SQL changes must be reviewed by the SDK team. For guidelines on custom sql, read up here: https://docs.q2developer.com/guides/database/custom_sql.html |
Javascript: eval() function |
Q2 does not allow the use of eval() in Javascript for security reasons. Please use a different implementation |
Filesystem interaction |
We suggest using https://docs.q2developer.com/api_references/q2_sdk/core/q2_open.html#module-q2_sdk.core.q2_open |
Python: exec() and eval() |
Q2 does not allow the use of exec or eval in python code for security reasons. Please use a different implementation |
Python: global keyword |
Refactor to use function parameters and return values instead of global variables. |
Javascript: document.createElement(‘script’) |
Use static <script src=’…’ integrity=’…’> tags instead of dynamically creating scripts. |
Python: sys.exit() |
Use exception handling instead of sys.exit(). |
Usage of self.application |
self.application in tornado can inadvertantly lead to memory sharing across requests and is therefore disallowed. Perhaps rely on self.cache instead. |
Medium Severity Rules
Rule |
Mitigation |
|---|---|
Python: logger.error() inside exception block |
Use logger.exception() or logger.error(…, exc_info=True) to include the full traceback. |
Suggested WedgeOnlineBanking imports |
|
React: dangerouslySetInnerHTML usage |
Verify that content passed to dangerouslySetInnerHTML is sanitized using a library like DOMPurify to prevent XSS attacks |
Possible XSS attack vectors |
Ensure all user input is sanitized before using innerHTML/insertAdjacentHTML to prevent XSS attacks. |
Legacy platform interactions |
|
Environment variable interaction |
We recommend using configuration files instead of os.environ for sensitive values. |
Parent window access |
We recommend using window.Tecton |
Javascript: Script imports without integrity values |
Add integrity=’sha384-…’ attribute to external script tags. Generate hashes at https://www.srihash.org/ |
time.sleep() |
Prefer using asyncio.sleep() for async code or implement proper retry/backoff patterns. |
Python: Check for skipped ssl verification. Can be allowed depending on reasoning |
Please provide reasons for disabling SSL verification in your merge request description. |
Low Severity Rules
Rule |
Mitigation |
|---|---|
Javascript: setInterval and setTimeout |
|
HTML: <a> tag or JavaScript calling openURL |
|
Javascript: console.log() |
Consider using console.debug instead of console.log |
Usage of 100vh |
|
Nested iframe usage |
|
Usage of q2-action-sheet |
|
Usage of q2-modal |
|
Usage of q2-option-list |
|
Usage of q2-popover |
|
Usage of q2-toast |
|
Usage of stencil-hydrated class |
Context Tracking
q2-sdk version
Tracking classes in repo
Python: Tracking user input access
Tracking third party cache usage in repo