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 .env and .cache directories

  • Skips B101 (assert statements) to reduce noise

  • Produces bandit-report.json artifact

  • Allowed 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, main or master that 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 json always exits 0. Read result from the JSON body instead of checking the exit code.

  • --scan-type local-diff requires 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. Run q2 review rb versions to print everything the manifest advertises.

  • To pin a different version, pass --rb-version or set Q2SDK_REVIEW_BUDDY_VERSION. To run a locally compiled build, point Q2SDK_REVIEW_BUDDY_PATH at 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