Microsoft Application Inspector: a rule-based source code characterization tool
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.
At a glance
- What is it?
- Application Inspector scans source trees for library and API patterns and reports what features a component contains. It answers what the code does, not whether it is safe, and the rule set is the part you will end up maintaining.
- Who is it for?
- Adopt Application Inspector when you need a fast, language-agnostic inventory of what a component does before you take it on, or when you want to diff feature tags between two versions of the same code. Skip it if you want a vulnerability scanner that flags exploitable code: the README is explicit that it does not judge patterns as good or bad, and the output is a feature report, not a finding list.
- 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 14 days 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 September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Application Inspector answers that a dependency scanner does not
A package manifest tells you a name and a version. It does not tell you that the component opens sockets, shells out, or reaches a cloud API. Application Inspector is built for that gap. According to the README, it identifies coding features of first or third party software components based on well-known library and API calls, and it reports what it finds against a set of over 400 rule patterns covering cryptography, file operations, shell operations, cloud APIs and frameworks.
The intended reader is someone doing due diligence on code they did not write: an engineer evaluating an open source component before adoption, or a team lead who wants to know which of their internal projects pull in crypto libraries. The README frames three uses: picking components with a smaller footprint of unnecessary features, detecting feature deltas between component versions, and automating compliance checks in a build pipeline.
One design decision shapes everything else. The tool does not attempt to identify good or bad patterns. It is a characterization tool, not a verdict engine. If you want a list of findings with severities, this is the wrong shape of output, and treating a feature report as a security report is the most common way to misread it.
How the rules engine and the analyze command fit together
The repository splits into AppInspector.CLI, AppInspector.RulesEngine, AppInspector.Commands and a few smaller projects. The CLI is a thin front end over the commands layer; the rules engine does the matching. Rules are JSON, and the repository carries rule-schema-v1.json at the top level, which is the schema those files are validated against.
The data flow is straightforward. You point analyze at a directory, a single file, or a compressed archive (.tgz or .zip). The tool walks the source, applies the rule patterns to files whose language it recognizes, and aggregates the matched tags into a report. Tags are the unit of output, not files. That is why the tagdiff command exists: it compares the unique tag values between two source paths rather than diffing text.
The CLI exposes six commands. analyze does the scanning, tagdiff compares two trees, exporttags lists the tags associated with rules without scanning anything, verifyrules checks custom rule syntax, packrules merges multiple rule files into one for distribution, and help and version do what you expect. The presence of verifyrules and packrules tells you the maintainers expect users to write their own rules, not just consume the shipped set. The README's contribution section says the same thing directly: there are many feature identification patterns yet to be defined, and it invites submissions.
Output formats are HTML, JSON and text, with HTML as the default. That default is worth knowing before you wire the tool into a pipeline, because a build step that expects JSON on stdout will get an HTML document unless you ask otherwise.
Installing Application Inspector and running a first scan
The recommended path is the .NET global tool. The README states you need the .NET 6 SDK first, then a single install command. The package name is Microsoft.CST.ApplicationInspector.CLI, and the command it installs is appinspector.
dotnet tool install --global Microsoft.CST.ApplicationInspector.CLIAfter that, the tool is on your PATH. If you prefer not to install a global tool, the releases page carries platform-specific binaries under the Assets section, including applicationinspector.cli.exe for Windows. The README gives both invocation forms.
appinspector analyze -s path/to/srcRun against a directory, that produces an HTML report by default. The README's own help output shows the analyze command described as inspecting a source directory, file or compressed file (.tgz or .zip) against defined characteristics, so you can hand it an archive instead of an unpacked tree.
When you want machine-readable output for a pipeline, ask for JSON explicitly and confirm the flag against `appinspector analyze --help` in your installed version, since the README documents the formats but not every flag. The same help output lists the other commands you will reach for next: tagdiff for comparing two source paths, and verifyrules before you commit a custom rule file.
appinspector tagdiff --helpIf you are embedding the tool rather than shelling out, the C# library is published separately as Microsoft.CST.ApplicationInspector.Commands on NuGet.
The ruleset is the product, and it is also the maintenance burden
Everything Application Inspector reports comes from rule patterns, and rule patterns are pattern matching. A feature detected means a pattern matched, not that the feature is reachable at runtime. A crypto API referenced in a dead code path will be reported the same as one on the hot path. The README does not claim otherwise, but the output format does not distinguish the two either, so a reader skimming an HTML report can easily over-read it.
The second consequence is coverage. The README lists C, C++, C#, Java, JavaScript, HTML, Python, Objective-C, Go, Ruby and PowerShell among supported languages and points to a wiki page for the full set. It does not enumerate the languages in the README itself. If your dependency tree is mostly Rust, Swift or Kotlin, check that wiki page before you plan around this tool, because a language that is not recognized contributes nothing to the report and the scan will still exit successfully.
The third is rule drift. Rules age as libraries change. A pattern written for one major version of a framework may miss the next one. The maintainers ship verifyrules and packrules precisely because custom rules are expected, which means at some point the accuracy of your report is your responsibility rather than the project's. That is a reasonable trade for a tool whose value is in the shipped rule corpus, but it is a real cost to budget.
Finally, mixed-language projects are supported, which the README states directly. That matters for the common case of a repository with a Python service, a JavaScript front end and a shell script directory: one scan covers all three.
Where Application Inspector is the wrong tool
If you need to know whether a dependency has a known CVE, this does not do that. It has no vulnerability database and no advisory feed. It reads source, not manifests, and it does not resolve versions.
If you need dataflow or taint analysis, this does not do that either. The README describes matching against library and API calls. There is no interprocedural reasoning described, no source-to-sink tracking, and no claim of it. Tools in the CodeQL family, which the repository itself uses for its own CodeQL workflow, work on a different model: they build a queryable database of the code and let you write queries over it. Application Inspector applies regex-style patterns to text and aggregates tags. The two answer different questions, and a project that needs the first will not be satisfied by the second.
There is also a practical limit on what a feature report can tell you about intent. The README's own framing, that the tool helps determine what the software is or what it does, is a statement about description, not judgement. A component that uses cryptography heavily is not thereby suspicious, and one that uses none is not thereby safe. The report is input to a human decision, and the tool is designed that way.
Alternatives and the actual difference in approach
The closest comparison is CodeQL. CodeQL compiles the target into a database and answers queries against a relational representation of the code, which allows path-sensitive questions like whether untrusted input reaches a sink. Application Inspector does not build a database and does not compile the target; it pattern-matches source text and aggregates feature tags. CodeQL is heavier to set up and language support is a function of the extractors available. Application Inspector is a single command against a directory and reports in seconds on the kind of question it was built for.
For the narrower job of detecting a feature delta between two versions of the same component, the built-in tagdiff command is the direct answer, and the README names detecting injection of backdoors as one motivation for that workflow. Nothing in the README suggests tagdiff does semantic diffing; it compares unique tag values between two source paths, so a change that alters behavior without adding or removing a matched pattern will not appear.
For dependency-level questions, a manifest scanner such as the ones built around package lockfiles is a different category entirely. Those know versions and advisories. Application Inspector knows source patterns. Running both is not redundant, but they do not substitute for each other.
Licence, releases and the cost of keeping up
The project is MIT licensed, with the licence in LICENSE.txt and a NOTICE.txt alongside it. MIT is permissive, so embedding the CLI or the Microsoft.CST.ApplicationInspector.Commands library in an internal pipeline raises no copyleft question. The NOTICE file is the thing to read if you redistribute, and the usual caveat applies: this is a description of the repository, not legal advice.
The release cadence is visible in the tags. v1.9.55 landed on 2026-01-22, v1.10.1 on 2026-08-26 and v1.10.2 on 2026-09-10. The last push to the repository was on 2026-09-15. The gap between January and August is worth noting if you pin a version: rule updates arrive with releases, so a pinned older build carries an older rule corpus.
Upgrade cost is low in the normal case, since the CLI and the library are separate NuGet packages and the rules ship inside them. The cost that is not zero is re-validating your own custom rules. If you have written rules and packed them with packrules, run verifyrules after an upgrade before trusting the output, because the schema the rules are checked against is versioned in the repository as rule-schema-v1.json and your rules were written against whichever version you had.
Editorial conclusion
Adopt Application Inspector when you need a fast, language-agnostic inventory of what a component does before you take it on, or when you want to diff feature tags between two versions of the same code. Skip it if you want a vulnerability scanner that flags exploitable code: the README is explicit that it does not judge patterns as good or bad, and the output is a feature report, not a finding list. Before you rely on it, verify two things in your own environment: that the ruleset covers the languages in your dependency tree (the wiki page lists the supported set and the README points there rather than enumerating it), and that the JSON output schema matches whatever consumes it downstream, since the CLI, the NuGet library and the platform binaries are separate packages that can move independently.
Frequently asked questions
What is Microsoft Application Inspector used for?
It characterizes source code by identifying coding features based on well-known library and API calls, and reports what a component is or does. The README names three uses: choosing components with fewer unnecessary features, detecting feature deltas between component versions, and automating security compliance checks in a build pipeline.
Is Microsoft Application Inspector a security scanner?
It is a source code characterization tool, not a vulnerability scanner. The README states it does not attempt to identify good or bad patterns; it reports what it finds against over 400 feature detection rules, including security-relevant features such as cryptography.
How do I install Microsoft Application Inspector?
The recommended route is the .NET global tool: install the .NET 6 SDK, then run dotnet tool install --global Microsoft.CST.ApplicationInspector.CLI. Platform-specific binaries are also available under the Assets section of the releases page.
Which programming languages can Microsoft Application Inspector scan?
The README lists C, C++, C#, Java, JavaScript, HTML, Python, Objective-C, Go, Ruby and PowerShell, and points to a wiki page for the complete set. It also states that projects with mixed language files are supported.
What is the difference between analyze and tagdiff in Microsoft Application Inspector?
analyze inspects a source directory, file or compressed file against defined characteristics. tagdiff compares unique tag values between two source paths, which the README presents as useful for detecting feature changes between component versions.
Official sources
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.
[](https://hysenlabs.com/projects/microsoft-applicationinspector)