As of June 2024, Beams completed the App Defense Alliance’s Cloud Application Security Assessment (CASA) Tier 2. If you are developing an app that uses Google APIs, you will likely need to go through some type of security assessment or verification. While the verification is beneficial for your users’ security and your brand, the process can sometimes feel like walking in the dark.
I will summarize our journey below and provide you with a to-do list and a progress tracker. Hope it helps!

Overview

 
Google APIs have three types of scopes:
  • Free scopes, like profile info
  • Sensitive scopes, like accessing calendar
  • Restricted scopes, like email or Google Drive access
Except for free resources, third-party apps like Beams need to go through a verification process.
For sensitive scopes, Google verifies that the app has a legitimate use case for the permissions.
For restricted scopes, Google requires third-party apps to undergo a CASA verification. CASA stands for Cloud Application Security Assessment. It has three tiers, and Google mandates Tier 2 or Tier 3 verification based on the security risk posed by the requested scopes. Beams needs to get a Tier 2 verification.
As of May 2024, an app can achieve Tier 2 verification via an accredited security lab.
For more information on CASA and its tiers, click here.
The high-level process for Tier 2 verification includes:
  • Self-scan
    • Patching vulnerabilities
  • Documenting the security architecture and data classification practices
  • Scheduling a scan with a security lab
  • Back-and-forth communication with the lab
  • Receiving a Letter of Verification (LOV) from Google

Important Resources

  • Fluid attacks
    • Fluid attacks is the recommended static scan tool by Google, however the instructions on Google’s page are not up to date. Follow the instructions from fluidattacks

Self Scan

🔗 Copy this checklist and requirements tracker

 
Getting Ready:
Create a spreadsheet like this, by exporting the official CASA Tier 2 requirements from Google. This is very important in terms of tracking the progress, make sure you comment on each requirement, it will be necessary later on.
On your workspace create folder for casa work mkdir -p ~/workspace/casa
Install Docker
 
Static Scan:
Static scan is scanning the code and search for vulnerabilities like bad Dockerfile practices or using insecure random number generators or having secrets in the code.
Although Sonar cloud is a much better tool, Fluidattacks is a free alternative and can output result reports that you can use for applying for verification.
 
cd ~/workspace/casa
git clone <your repository>.git
Create a fluidattacks configuration and place it in the ~/workspace/casa folder. Sample configuration
Stay in ~/workspace/casa
 
The following commands run the scan using fluidattacks’s docker image for their scan tool. Pick the correct image for your CPU architecture.
Little explanation: It mounts ~/workspace/casa folder on your machine to the docker image’s /working-dir folder. So all reference to working-dir folder in the config files refer to ~/workspace/casa on your machine.
 
docker run -v /Users/<your_user>/workspace/casa:/working-dir fluidattacks/cli:arm64 skims scan /working-dir/<fluid-config>.yaml
 
Based on the configuration we provided, these commands will produce two results, you may need them, depending on the requirements of the process in 2025.
  • fluidattacks-backend-sast.csv
 
Dynamic scan:
This is the most time consuming part of the self scan procedure. ZAProxy does a comprehensive scan and it takes a long time. It is important to do address as many vulnerabilities as possible between scans to progress quicker.
ZAProxy is also an open source tool that is free and is recommended by Google.
 
Create a JWT or credentials for a test user on beams api and copy this somewhere.
Create ZAPRoxy configurations similar to the ones I provided below
Update the configuration files according to the info provided in the pages above with the JWT you just copied and the URL of the environment you want to test.
Run dynamic scan for your api.
docker run -v $(pwd):/zap/wrk:rw -t zaproxy/zap-weekly zap-full-scan.py -t <WEB URL> -c /zap/wrk/zap-casa-config.conf -n appscan.context -z "-configfile /zap/wrk/zapconfig-web.conf" -r results-web.html -x results-web.xml -j -d
Run dynamic scan for your webapp
docker run -v $(pwd):/zap/wrk:rw -t zaproxy/zap-weekly zap-api-scan.py -t <API URL> -f openapi -c /zap/wrk/zap-casa-config.conf -n apiscan.context -z "-configfile /zap/wrk/zapconfig-api.conf" -r results.html -x results.xml -d

Document Security Practices

Your documentation should address the following requirements that you can find in the progress tracker:
  • Verify documentation and justification of all the application's trust boundaries, components, and significant data flows.
  • Verify that trusted enforcement points, such as access control gateways, servers, and serverless functions, enforce access controls. Never enforce access controls on the client.
  • Verify that all sensitive data is identified and classified into protection levels.
  • Verify that all protection levels have an associated set of protection requirements, such as encryption requirements, integrity requirements, retention, privacy and other confidentiality requirements, and that these are applied in the architecture.

Work with a security lab

 
We chose TAC security in 2024 for various reasons. They provided us an interface to
Schedule a scan
Fill out a survey: you’ll be mostly copying comments from this document
Patch or justify vulnerabilities they find.

Reverification

Google requires that we go through pretty much the same process every year, with one difference. We apply for re-verification and not first time verification.
 

More Resources

Sample fluidattacks configuration

Configuration
# Description: # Pick a name you like, normally the name of the repository. # Example: namespace: beams-api # Description: # Omit if you want pretty-printed results, # Set to a path if you want CSV results. # Optional: # Yes # Example: output: file_path: /working-dir/fluidattacks-backend-sast.csv format: CSV # Description: # Working directory, normally used as the path to the repository. # Example: working_dir: /working-dir/api # Description: # SAST for source code. # Example: sast: include: - . exclude: - glob(**/*spec.ts) - glob(**/dist) - glob(**/coverage) - glob(**/node_modules) recursion-limit: 100 sca: include: - . # Description: # Findings to analyze. # The complete list of findings can be found here: # https://gitlab.com/fluidattacks/universe/-/blob/trunk/skims/manifests/findings.lst # Optional: # Yes, if not present all security findings will be analyzed. # Example: checks: # Description: # Language to use, valid values are: EN, ES. # Optional: # Yes, defaults to: EN. language: EN debug: true

Sample ZAProxy configurations

1. Context file

This file gives the scan context, which urls to include/exclude in the scan
apiscan.context
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <context> <name>api</name> <desc/> <inscope>true</inscope> <incregexes>https://api.usebeams.com/.*</incregexes> <excregexes>https://api.usebeams.com/api*</excregexes> <tech> <include>Db.MongoDB</include> <include>Language.JavaScript</include> <include>OS.MacOS</include> <include>SCM.Git</include> <exclude>Db</exclude> <exclude>Db.CouchDB</exclude> <exclude>Db.Firebird</exclude> <exclude>Db.HypersonicSQL</exclude> <exclude>Db.IBM DB2</exclude> <exclude>Db.Microsoft Access</exclude> <exclude>Db.Microsoft SQL Server</exclude> <exclude>Db.MySQL</exclude> <exclude>Db.Oracle</exclude> <exclude>Db.PostgreSQL</exclude> <exclude>Db.SAP MaxDB</exclude> <exclude>Db.SQLite</exclude> <exclude>Db.Sybase</exclude> <exclude>Language</exclude> <exclude>Language.ASP</exclude> <exclude>Language.C</exclude> <exclude>Language.JSP/Servlet</exclude> <exclude>Language.Java</exclude> <exclude>Language.Java.Spring</exclude> <exclude>Language.PHP</exclude> <exclude>Language.Python</exclude> <exclude>Language.Ruby</exclude> <exclude>Language.XML</exclude> <exclude>OS</exclude> <exclude>OS.Linux</exclude> <exclude>OS.Windows</exclude> <exclude>SCM</exclude> <exclude>SCM.SVN</exclude> <exclude>WS</exclude> <exclude>WS.Apache</exclude> <exclude>WS.IIS</exclude> <exclude>WS.Tomcat</exclude> </tech> <urlparser> <class>org.zaproxy.zap.model.StandardParameterParser</class> <config>{"kvps":"&amp;","kvs":"=","struct":[]}</config> </urlparser> <postparser> <class>org.zaproxy.zap.model.StandardParameterParser</class> <config>{"kvps":"&amp;","kvs":"=","struct":[]}</config> </postparser> <authentication> <type>0</type> <strategy>EACH_REQ_RESP</strategy> <pollurl/> <polldata/> <pollheaders/> <pollfreq>60</pollfreq> <pollunits>REQUESTS</pollunits> </authentication> <forceduser>-1</forceduser> </context> </configuration>

2. ZAP Application config

This is application config for ZAP, we use it to replace each request header’s authorization field with a valid token
zapconfig-api.conf
replacer.full_list(0).description=Authorization replacer.full_list(0).enabled=true replacer.full_list(0).matchtype=REQ_HEADER ## Replace this with cookies if required replacer.full_list(0).matchstr=Authorization replacer.full_list(0).regex=false replacer.full_list(0).replacement=Bearer <JWT>

3. CASA Config

This one is provided by Google and can be downloaded from here. It sets the criteria for the scan, what fails and not.
zap-casa-config.conf
# zap-api-scan rule configuration file # Change WARN to IGNORE to ignore rule or FAIL to fail if rule matches # Active scan rules set to IGNORE will not be run which will speed up the scan # Only the rule identifiers are used - the names are just for info # You can add your own messages to each rule by appending them after a tab on each line. 0 WARN (Directory Browsing - Active/release) 548 10010 WARN (Cookie No HttpOnly Flag - Passive/release) 1004 10011 WARN (Cookie Without Secure Flag - Passive/release) 614 10015 WARN (Incomplete or No Cache-control and Pragma HTTP Header Set - Passive/release) 525 10017 WARN (Cross-Domain JavaScript Source File Inclusion - Passive/release) 829 10019 WARN (Content-Type Header Missing - Passive/release) 345 10023 WARN (Information Disclosure - Debug Error Messages - Passive/beta) 200 10024 WARN (Information Disclosure - Sensitive Informations in URL - Passive/beta) 200 10025 WARN (Information Disclosure - Sensitive Information in HTTP Referrer Header - Passive/beta) 200 10027 WARN (Information Disclosure - Suspicious Comments - Passive/beta) 200 10040 WARN (Secure Pages Include Mixed Content - Passive/release) 311 10048 WARN (Remote Code Execution - Shell Shock - Active/beta) 78 10105 WARN (Weak Authentication Method - Passive/beta) 326 10202 WARN (Absence of Anti-CSRF Tokens - Passive/beta) 352 2 WARN (Private IP Disclosure - Passive/release) 200 20012 WARN (Anti CSRF Tokens Scanner - Active/beta) 352 20014 WARN (HTTP Parameter Pollution scanner - Active/beta) 20 20017 WARN (Source Code Disclosure - CVE-2012-1823 - Active/beta) 20 20018 WARN (Remote Code Execution - CVE-2012-1823 - Active/beta) 20 20019 WARN (External Redirect - Active/release) 601 3 WARN (Session ID in URL Rewrite - Passive/release) 200 40012 WARN (Cross Site Scripting (Reflected) - Active/release) 79 40014 WARN (Cross Site Scripting (Persistent) - Active/release) 79 40016 WARN (Cross Site Scripting (Persistent) - Prime - Active/release) 79 40017 WARN (Cross Site Scripting (Persistent) - Spider - Active/release) 79 40018 WARN (SQL Injection - Active/release) 89 40019 WARN (SQL Injection - MySQL - Active/beta) 89 40020 WARN (SQL Injection - Hypersonic SQL - Active/beta) 89 40021 WARN (SQL Injection - Oracle - Active/beta) 89 40022 WARN (SQL Injection - PostgreSQL - Active/beta) 89 40023 WARN (Possible Username Enumeration - Active/beta) 200 90019 WARN (Server Side Code Injection - Active/release) 94 90020 WARN (Remote OS Command Injection - Active/release) 78 90021 WARN (XPath Injection - Active/beta) 643 90022 WARN (Application Error Disclosure - Passive/release) 200 90023 WARN (XML External Entity Attack - Active/beta) 611
 
🤙
If you have any questions, reach us at team@usebeams.com