Author's note: This article describes my first-hand experience building MISPFuse and REST Profiler for Splunk. The versions and validation results are identified where relevant because Splunk, UCC, AppInspect, Python, and platform requirements continue to evolve. Project and evidence links MISPFuse source repository REST Profiler source repository REST Profiler for Splunk on Splunkbase Complete article, threat model, and SSDLC roadmap Sanitized UCC/AppInspect compatibility evidence My GitHub profile I began building MISPFuse to solve a practical security-operations problem: move selected Splunk search results into MISP without turning the integration into an unrestricted data-export mechanism. The first version had no dedicated user interface. It was a direct Splunk SDK prototype with a custom streaming command and minimal infrastructure. UCC came later—and it was a major improvement. This article explains why I still believe the UCC Framework is important to the Splunk ecosystem, what happened when current UCC-generated output conflicted with AppInspect 4.3.0, and what I would recommend to another Splunk application developer. MISPFuse began with the security problem The original proof of concept answered a narrow question: could Splunk results be transformed into MISP events and attributes? It also had the expected limitations of a prototype. The public project history records a key and URL in a Python file, disabled TLS verification, fixed organization and tag values, IP-oriented handling, one event per row, no alert action, and no configuration UI. That stage was useful because it made the risks visible. The important design questions were: Who is authorized to export data? Which fields are allowed to leave Splunk? Which destination is approved? How are API keys protected and rotated? How are search-result values validated? How do retries avoid duplicate MISP events? How does the app behave when MISP is slow or unavailable? The backend—not the UI—had to remain the security boundary. The security model had to exist below the UI The key risk was not only protecting the MISP API key. MISPFuse crosses an authorization and data-governance boundary. A user can be allowed to search data without being allowed to export it, and a configured URL makes the Splunk search head initiate a server-side network request. The design therefore had to address server-side authorization, encrypted secret storage, TLS validation, destination controls, bounded response sizes, timeouts, retries, secret-safe logging, and the integrity of mappings. These checks must exist in the command, alert action, and REST handlers; a hidden or disabled UI control can always be bypassed. Splunk's own guidance for custom search commands emphasizes secure input handling and the privileged execution context. Developers should review Security responsibilities for custom search commands before treating a custom command as a simple utility. Availability also belongs in the threat model. A large result set or an unavailable MISP server can consume search-head resources unless row counts, timeouts, retries, and concurrency are bounded. Retries also need an idempotency strategy because a request may have succeeded even when its response was lost. This is why the original UI-less phase was valuable. It forced the trusted backend contract to exist before the convenience layer was added. Why UCC improved the application As MISPFuse matured, manual configuration became an operational risk. Administrators needed to manage multiple connections, encrypted credentials, proxies, logging, reusable mappings, connection tests, a custom command, and an alert action. UCC generated much of that standard Splunk infrastructure. The key moved into Splunk encrypted credential storage. Accounts became selectable. Proxy and logging settings became manageable. Field mappings became reusable templates. The command and alert action shared the same core push logic. The current project also documents connection validation before account save, TLS verification by default, secret redaction, response-size limits, disabled redirects and decompression, hash-locked dependencies, and release checks that reject native binaries. This is why I see UCC as a major step forward. Without common patterns, every developer may implement credential storage, configuration REST handlers, permissions, metadata, packaging, and validation differently. UCC can reduce fragmented and inconsistent plugins, provide administrators with a familiar experience, and allow common fixes to benefit many applications. UCC does not replace threat modeling or secure coding. It raises the baseline. Why standardization improves security UCC's broader ecosystem value is that common infrastructure can be improved once instead of being reinvented in every add-on. A consistent credential workflow, configuration API, metadata model, and packaging layout is easier for developers to maintain, for Splunk to review, and for administrators to operate. That does not remove application responsibility. UCC cannot decide whether a user is allowed to export a field, whether a MISP destination is approved, or whether a mapping violates an organization's sharing policy. The framework raises the baseline; threat modeling and business-logic security remain with the application author. The central framework risk You own the application, but you do not fully control the generated package. The application author remains accountable for every shipped file. UCC may generate UI loaders, JavaScript, REST handlers, configuration, metadata, and runtime dependencies. That means UCC must be managed as a software-supply-chain dependency rather than treated as an invisible build step. The AppInspect 4.3.0 conflict REST Profiler for Splunk was built with UCC 6.5.3. The package built and its local release checks passed. AppInspect 4.3.0 then returned a future failure for: check_for_custom_mako_templates
appserver/templates/base.html This was confusing because UCC 6.3.0 had removed Mako and CherryPy from its generated templates. UCC's implementation describes base.html as plain HTML with app values injected at build time. UCC 6.5.3 still generated that static file under appserver/templates/, and the generated Configuration and Dashboard views referenced it. Deleting it without replacing the view architecture would break the UI. I then inspected MISPFuse with the actual AppInspect 4.3.0 engine. It produced the same future failure. MISPFuse AppInspect 4.3.0 result Count Errors 0 Failures 0 Future failures 1 Warnings 8 Successes 117 The separate AppInspect check for Python code blocks in a Mako template passed. The path-based custom-template check returned the future failure. The contradiction was: UCC generated the file.
The UI depended on the file.
The file was static rather than executable Mako.
AppInspect classified the path as a future failure. The correct response was not to ignore exit code 104 or delete a generated dependency blindly. It was to preserve the exact package and JSON report, keep the release gate closed, document the reproduction, and request a supported resolution. The AppInspect CLI reference should be part of the CI/CD documentation because native exit codes and selected tags are part of the validation evidence. What this taught me about releases A Splunk app can be: buildable; installable; functionally correct in a test environment; but not acceptable under the current Cloud validation policy. Those are different states. The release pipeline should record the application version, Git commit, Python version, UCC version, AppInspect version, resolved dependencies, package checksum, and report checksum. The package should be built once. That same package should be tested, inspected, checksummed, and published. AppInspect is a gate, not the whole security assessment AppInspect is necessary, but a passing report cannot prove that authorization, data-sharing policy, retry integrity, or operational monitoring are correct. Those questions require threat modeling, negative testing, integration testing, upgrade testing, and manual review. The opposite is also important: a future failure should not be ignored merely because the feature works today. It is evidence that a current design is moving outside the supported platform contract. The release pipeline should preserve that evidence and block publication until the risk is understood or an official exception exists. Release evidence matters as much as the build result The package should be produced once and promoted through verification without rebuilding it. The release record should identify the Git commit, Python version, UCC version, AppInspect version, resolved runtime dependencies, package checksum, and report checksum. That makes it possible to reproduce a result when AppInspect or a dependency changes later. Failed runs should also preserve their artifacts. In this case, the native exit code, package, JSON report, and checksums were necessary to show that the blocker came from the generated path rather than a generic CI failure. Converting the result to success would have hidden evidence that Splunk's future platform contract had changed. This distinction is important for Splunkbase and Cloud development: a package can build, install, and work in a test instance while still being unsuitable for publication under the current policy. Those states should be reported separately rather than compressed into a single green or red badge. The wider compatibility tax The UCC/AppInspect conflict was the clearest example, but Splunk app developers also manage other moving layers. Splunk Enterprise 10.4 changes the default Python runtime to 3.13 with Python 3.9 as fallback. Applications need exact runtime support statements, not only “Python 3 compatible.” Splunk 10.4 also moves KV Store and KV Service to MongoDB 8.0 and documents intermediate upgrade requirements for some older deployments. Apps that use KV Store inherit part of that lifecycle: availability, backup, schema compatibility, cluster behavior, TLS settings, and rollback planning. UCC applications also depend on splunktaucclib, solnlib, the Splunk SDK, HTTP libraries, and front-end packages. Pinning only the UCC version is not a reproducible build. AppInspect itself changes. An unchanged package can receive a different result after a validator or policy update. My roadmap for another Splunk developer Start with the problem and trust boundaries, not with UCC or another framework. Keep business logic independent from generated handlers. Use thin Splunk adapters around testable core modules. Use Splunk secret storage, least privilege, server-side authorization, secure TLS defaults, destination controls, timeouts, response limits, and bounded retries. Inspect the generated package. Pin and hash dependencies. Reject unexpected binaries. Generate an SBOM and preserve checksums. Run unit, negative, integration, upgrade, performance, and topology tests. Test malicious inputs, forbidden destinations, invalid certificates, missing permissions, large result sets, timeouts, and partial failures. Run AppInspect continuously rather than waiting for Splunkbase submission. Preserve failed reports because they are engineering evidence. Publish a security policy and define how to rotate credentials, disable outbound behavior, respond to vulnerabilities, and retire the app. What I would like Splunk to improve One compatibility matrix connecting Splunk Enterprise and Cloud releases with Python, UCC, splunktaucclib, solnlib, the SDK, AppInspect, front-end frameworks, and KV Store versions. Every UCC release should generate a reference app and run it through current Cloud AppInspect checks. AppInspect reports should make validator and policy versions visible and distinguish application-owned findings from generator- and dependency-owned findings. When a generated pattern becomes a future failure, developers need a supported replacement, reference implementation, migration guide, known-good framework version, and timeline. Why I remain positive The work that created these compatibility challenges is mostly necessary work. Unsupported Python and MongoDB versions must be retired. TLS must improve. Legacy web mechanisms should be removed. Cloud apps need stronger validation. Developers need shared frameworks. UCC is part of the solution because it can reduce scattered and inconsistent implementations. AppInspect is part of the solution because it exposes problems before users inherit them. The issue is coordination, not direction. My main lesson is: Build security into the backend, use UCC where it improves consistency, inspect everything it generates, and treat compatibility as part of the product from the first commit. Continue reading and review the projects Read the complete security architecture and SSDLC article Review the sanitized AppInspect compatibility evidence Explore MISPFuse on GitHub View REST Profiler for Splunk on Splunkbase Explore REST Profiler source on GitHub MISPFuse and REST Profiler are independent projects. This article is based on my own development experience and is not an official Splunk statement.
... View more