CLI tool
microsoft/ApplicationInspector avatar
microsoft/ApplicationInspector

Microsoft Application Inspector: what a component does, not whether it is bad

A source code analyzer built for surfacing features of interest and other characteristics to answer the question 'What's in the code?' quickly using static analysis with a json based rules engine. Ideal for scanning components before use or detecting feature level changes.

4,402 stars366 forksC#MIT

At a glance

What is it?
Microsoft Application Inspector reads source code and reports which API and feature patterns a component uses, using a JSON rules engine with over 400 patterns instead of good or bad verdicts. It suits engineers vetting a third party library or comparing two component versions.
Who is it for?
Adopt Application Inspector when a component's own documentation tells you nothing about which crypto, shell or cloud APIs it reaches for, and when you can afford to read source yourself. Skip it when you need a vulnerability verdict, a CVE list or a pass or fail build gate, because tagdiff and the rule set describe features rather than defects.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • microsoft/ApplicationInspector4,402 ★ · +9
Star history
Repository2026-09-232026-11-14
microsoft/ApplicationInspector4.4k4.4k

9 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Over 400 rule patterns instead of a good or bad verdict

Application Inspector starts from an unusual position for a static analyzer. It does not try to decide whether code is good or bad. It reports what it finds against a set of more than 400 rule patterns aimed at feature detection, and the README is explicit that features carrying security weight, cryptography among them, are part of the same set as everything else. That single decision shapes the whole tool. A security-oriented analyzer answers a question about defect, and its silence means no known defect. Application Inspector answers a question about content, and its silence means no matching pattern.

The audience is anyone who has to answer what a dependency actually does before shipping it. The README frames this as reducing the time needed to understand an open source or other component by examining the source directly rather than trusting thin documentation or a recommendation from someone else. That fits a security review, a procurement decision, and an inventory of what an enterprise application pulls in. Three goals are named in the project: keeping the attack surface smaller by choosing components with fewer unknown features, identifying feature deltas between component versions, and flagging components that need extra scrutiny or SDL compliance as part of a build pipeline.

The delta goal is the most distinctive. A new version of a library that suddenly starts shelling out or begins calling a crypto API it never touched before is a signal worth stopping on, and the tool exists to make that signal cheap to compute.

A single rules engine reading C, C#, Java, Go and PowerShell together

Scanning mixed-language code is where a tag based approach earns its keep, and the repository layout shows how much of the work is parsing rather than judging. The repository root holds AppInspector, AppInspector.Common, AppInspector.RulesEngine, AppInspector.CLI and AppInspector.Logging as separate projects, so language handling, rule matching, logging and the command surface are cut apart rather than tangled in one executable. The rules engine is its own assembly with a schema file, rule-schema-v1.json, at the repository root, which means the pattern definitions are data with a versioned contract rather than compiled code.

The documented language set covers C, C++, C#, Java, JavaScript, HTML, Python, Objective-C, Go, Ruby and PowerShell, with a longer list held in the project wiki. A repository holding both Python and C# still produces one report.

One number in the README is easy to skim past. The introduction calls the pattern set "hundreds of rules and regex patterns" while a later paragraph says "over 400 rule patterns". Both refer to the same JSON rule engine, and the two figures do not contradict each other. For anyone budgeting review time, the useful number is the tag vocabulary rather than the pattern count, and the CLI exposes that directly through exporttags.

Installing the .NET 6 global tool and running the first analyze

The recommended path is a .NET global tool, which needs the .NET 6 SDK installed first. On Linux and macOS that means the dotnet command has to be on the path before the tool will install.

bash
dotnet tool install --global Microsoft.CST.ApplicationInspector.CLI

The alternative is a platform dependent binary picked for your operating system from the published packages, which gives you applicationinspector.cli.exe on Windows or the matching binary elsewhere. The trade-off is that the binary is a fixed build, so upgrading means downloading a new package rather than changing a version number.

With the tool installed, the first run points it at a directory of source and writes an HTML report into the current directory.

bash
appinspector analyze -s path/to/src

The output file is named output.html and uses default arguments and default rules. To confirm the tool itself works, run appinspector --help and read the version banner, then pick a small directory before pointing it at a large vendored tree, because the scan is done by the engine in AppInspector rather than by a lightweight text search and a big tree takes time.

output.html by default, markdown and sarif only when asked

Output format is the first decision after the scan path, and the defaults are deliberately not the automation friendly ones. The README states that HTML, JSON and text are supported with HTML as the default, which is a report built for a human reading a component for the first time. A pipeline wants something else.

For CI, the markdown format gives a summary of key features.

bash
appinspector analyze -s path/to/files -f markdown -o report.md

For tooling that already speaks the standard static analysis interchange format, the sarif option writes a single sarif file.

bash
appinspector analyze -s path/to/files -f sarif -o output.sarif

That third one carries a caveat worth stating plainly. The README documents the flag in its examples.

The compression support sits on the same command line. analyze accepts a source directory, a single file, or a compressed file with a .tgz or zip extension, so a vendored dependency can be scanned from the archive a build system already produces.

tagdiff, exporttags, verifyrules and packrules around the same engine

Five subcommands share one binary, and three of them exist because the rule set is meant to be edited rather than accepted as fixed. The README invites contributions of new feature identification patterns, which only works if a custom rule file can be checked and distributed.

verifyrules checks that a custom rule file is syntactically valid against the same schema that rule-schema-v1.json describes. Running it after every edit is the difference between a broken rule file and a scan that quietly finds nothing. packrules merges several rule files into one so a set of in house patterns can be shipped to a team without checking four files into every repository. exporttags lists the tags attached to the named rules and does not scan source code at all, which makes it the cheapest way to see what vocabulary the current rule set actually offers.

tagdiff compares unique tag values between two source paths. This is the command that turns the tool from a curiosity into a supply chain instrument: scan the version you already approved, scan the candidate, diff the tag sets, and read the additions. A new shell execution tag in a patch version is a concrete finding. It is still not a backdoor verdict, though the README's goals say detecting changes between component versions can be critical for detecting injection of backdoors.

Mixed-language repositories are handled by the same pass, so a tagdiff between two versions of a polyglot monorepo produces one tag set to compare.

A tag report cannot tell you whether any of it is wrong

The central limitation follows from the central design choice. Application Inspector reports presence, so it cannot report absence of harm. A component that encrypts data, spawns shells and calls cloud endpoints may be entirely correct for its job, and the report will look identical to one that does the same things maliciously. The README's own framing is that it does not attempt to identify good or bad patterns, which is a strength for triage and a dead end for assurance.

The second failure mode is rule coverage. Findings depend entirely on patterns someone wrote. A call into an SDK that no rule pattern mentions produces no tag. The repository carries log files at the root, appinspector.log.txt and log.txt.

The third is the version signal. The help output quoted in the README shows ApplicationInspector.CLI 1.8.4-beta+976ee3cdd1 while the Releases page lists v1.10.2 dated 2026-09-10, so the documented help text sits behind the shipped binaries and the CLI excerpt should be read as illustrative. The last push was on 2026-09-15 and the repository is not archived, with v1.10.1 dated 2026-08-26 and v1.9.55 dated 2026-01-22 behind it. Keep your own copy of any custom rules file rather than assuming the rule schema version is stable across upgrades.

Where Application Inspector sits against SAST and manifest scanners

Two other tools answer neighbouring questions, and the difference is in what gets read.

Semgrep and similar pattern-matching static analysis tools work from rule files too, but their rules encode bugs and the code shapes that cause them, and the output is a set of findings at locations with severities. The engine idea is comparable. The intent is inverted: Application Inspector's rules encode capabilities, so a hit is a fact about the component rather than an accusation. If your question is what this library can do, Application Inspector answers it and Semgrep does not.

OWASP Dependency-Check and similar component tools read manifests and package metadata and compare known vulnerabilities against them. They never open the source, so they cannot see a crypto API called directly in a vendored file, and they cannot diff two versions of a component you already have on disk. Application Inspector reads the source and knows nothing about published vulnerability databases.

That makes the two families complementary rather than rival. Run a manifest scanner to get the known bad list, then run Application Inspector on what survives to see the capability surface, then use tagdiff between two versions to see what changed in that surface.

Editorial conclusion

Adopt Application Inspector when a component's own documentation tells you nothing about which crypto, shell or cloud APIs it reaches for, and when you can afford to read source yourself. Skip it when you need a vulnerability verdict, a CVE list or a pass or fail build gate, because tagdiff and the rule set describe features rather than defects. Before committing, run analyze on a component you already trust and check whether its tags match what you know the library does, since a miss there means the rule set is thinner than its pattern count states.

Frequently asked questions

How do I install Microsoft Application Inspector?

Install the .NET 6 SDK, then run dotnet tool install --global Microsoft.CST.ApplicationInspector.CLI. A platform specific binary is also published for Windows, Linux or macOS.

What does Microsoft Application Inspector report?

It reports the features it finds in source code against a set of over 400 rule patterns, covering cryptography, file operations, shell execution, cloud APIs and frameworks. It does not classify the code as good or bad.

Which languages does Microsoft Application Inspector scan?

The README lists C, C++, C#, Java, JavaScript, HTML, Python, Objective-C, Go, Ruby and PowerShell, with a fuller list in the project wiki. Projects containing mixed language files are scanned in one pass.

What is the difference between the analyze and tagdiff commands?

analyze scans a directory, file or compressed archive against the rules and writes a report. tagdiff compares the unique tag values between two source paths, which is how you spot a feature added between two component versions.

Can I write my own rules for Microsoft Application Inspector?

Yes. The project invites contributions of new feature identification patterns, and the commands verifyrules and packrules check custom rule syntax and combine multiple rule files into one for distribution.

Official sources

  1. Issues
  2. License: MIT
  3. microsoft/ApplicationInspector on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/microsoft-applicationinspector.svg)](https://hysenlabs.com/projects/microsoft-applicationinspector)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/microsoft-applicationinspector.svg)](https://hysenlabs.com/projects/microsoft-applicationinspector)

Was this useful?