Tuesday, April 22, 2025

SPExAI Report Builder: A Winning Sitecore Hackathon Module

The results of the 2025 Sitecore Hackathon are in...

Look what I got! 😭👇

It's a really decent piece of hardware!

I'm super proud of this accomplishment, given that I was pushing into delirium territory near the end of the event, having been up for 32 hours straight and all...running on mostly caffeine and adrenaline to get it done. 

Here's a snapshot of my real-time X updates throughout the event:



Sitecore Hackathon?

It's a virtual community-driven event where teams worldwide (52 teams across 13 countries this year) compete to build the most impactful Sitecore module given a set of categories (e.g., "Best use of AI" or "Best tool for XM Cloud") within a strict 24-hour timeframe.

Typically, the event is held in late February / early March, with teams registering roughly 4-6 weeks in advance. Submissions are then judged by a panel of long-time Sitecore MVPs and community members who review each completed entry, test the functionality, and collectively pick a winner.  

Submission Requirements are clearly laid out in the GitHub repository to which each team is assigned:

Winner Benefits

  • 🗣 Name recognition across Sitecore's official channels; the winning team is announced officially at SUGCON Europe and highlighted in the MVP community.
  • 🛒 $150 Amazon Gift Card (per team member)
  • 🏆 A customized Hackathon trophy

My Past Hackathons

Wasn't my first rodeo! 🤠
Here's a rundown of my past Sitecore Hackathon participations:

The name "Sitecorepunk 2077" is a not-so-subtle reference to
the 2020 video game Cyberpunk 2077 (which, admittedly,
I've barely played, but I liked the play-on-words when I came up with it).

I kinda love that I'm a 2x Sitecore Hackathon winner now 😅


The Idea

This year, instead of multiple categories (and multiple winners), the organizer's idea prompt was simply:

"Free for all — you can create your own idea for the Hackathon solution. Show us what you got!" 

It was a huge opportunity to build without barriers, with one winning team to take it all. I've been waiting for an opportunity to bring this idea I've been mulling over in my head for months to life, and this was it. 

Problem Statement

The biggest hurdle for analyzing content and creating reports in Sitecore PowerShell Extensions (SPE) has always been the technical skill needed (PowerShell scripting/syntax + SPE-specific commandlets).  

You'd need to train up; learn how to query items using Get-Item and Get-ChildItem commands, declare an array object to store results, utilize for loops and if conditions, etc.  

And if PowerShell scripting isn't your thing, well...


In the age of generative AI though, this technical skills barrier can be dramatically lifted for non-technical Sitecore authors and admin, and/or drastically reduce the turnaround time for developers tasked with writing custom PowerShell reports.



Enter: SPExAI Report Builder

What is it?

SPExAI Report Builder is an installable Sitecore PowerShell Extensions module that allows users to describe their Sitecore report in natural language, which in turn generates a complete and reusable SPE script:

  • 🧠💻 Type your prompt
  • 📜💾 Generate a PowerShell script and save it
  • 🛠️🚀 Run it or modify it

"SPExAI" stands for Sitecore PowerShell Extension x Artificial Intelligence, which combines the power of SPE with modern LLM tech. 

Compatibility

SPExAI Report Builder works with Sitecore 10.x or later.  I tested on Sitecore 10.0, 10.3, and 10.4 during the event, but I'm pretty confident that it would also work with other versions, too.

I didn't get a chance to test this on XM Cloud, but given SPE's flexibility, it is likely compatible.


How about a quick demo?

Say you need to audit template usage across the content tree.

When activating SPExAI from the ribbon, a dialog appears where you set a title, select the root context for the report, and provide a description.

"Report of all templates (ID, Name, Path) and their usage count."



SPExAI generates this clean, complete, and reusable script, which is stored in a dedicated part of the content tree:

Running the generated script without any modifications (which, on its own, included an option to select a root context, making it easily reusable against different parts of the tree) provides an accurate result set!



Another demo!

"Report of all renderings (ID, Name, Path) and their usage count under a selected content root."

SPExAI again generates a clean, complete, and reusable script, stored again using the name provided:

Running the generated script confirms that the script has been correctly generated and provides expected results.  



What's truly amazing is that we can generate 75-100 lines of working PowerShell code in seconds.

The code is appropriately structured, cohesive, error-free, and ready to be run immediately—no developer needed!



How SPExAI Works (Under the Hood)

API Settings

Before anything runs, the module looks for a specific Sitecore item:
/sitecore/system/Modules/PowerShell/Script Library/SPExAI Report Generator/API Settings:

There are four required fields:
  • API Keyyour OpenAI secret key

  • Model – the ID of the OpenAI model to use (e.g. o3-mini-2025-01-31)

  • Knowledgebase – a markdown-formatted reference block full of Sitecore PowerShell examples, documentation, best practices, etc.  

  • System Prompt – the instruction template that tells the model exactly how to behave, respond, etc. 


The module will abort early if any of these are missing.

Model Selection

During development, I tried a few different OpenAI models. The one that gave me the most consistent, one-shot responses was o3-mini-2025-01-31.

If you want to try a different OpenAI model later, simply update the Model field with the name; no code changes are required. (Expanding beyond OpenAI to Anthropic Claude or Google Gemini is also possible as part of a potential future v2.)

The Knowledgebase

This field contains raw reference material to guide the AI's responses. Think of it as an internal code cookbook, mostly pulled from the official SPE documentation and a compiled generic collection of snippets from my private repository of PowerShell scripts.

It includes sample report formats, SPE-specific syntax, and usage patterns that the model should stick to when replicating and generating new reports.

Looks like this:

The System Prompt

This is the master instruction set. Essentially, "You are a Sitecore PowerShell assistant...you do this, this, and that..." with additional specific constraints and formatting rules.

It includes a {0} token that the Knowledgebase content replaces.

Check it out:


A good chunk of the hackathon effort was spent refining the directives that the model should abide by. With every test run, I found myself adding to the list of rules. 

Getting the model to stick to the directives was...challenging to say the least (one-shot prompting definitely has its limitations depending on the model).  

Finding the right combination of rules for the model to consider was tricky, and I'm sure both the base system prompt and the knowledge base content could use even further refinement beyond what I could get done before the deadline.  Either way, I feel like I struck a solid balance for v1.

The good news is that the module was built to easily modify the system prompt in the configuration item without touching the underlying code, hypothetically allowing you to continuously improve the final output. 

UX Flow

SPExAI provides a new button in the Sitecore Ribbon. When clicked, this button surfaces a dialog window for the user's input.  



Users fill out the Report Name, set the Report Scope (tree selector), and the Describe your Report fields.  

It takes only a few seconds for the script to be generated.  

Users are then presented with the following options:



SPExAI Code Breakdown

Here's how the pieces come together behind the scenes:

1. Load the API Settings

The script set the four field values into variables.


2. Present a dialog for user input

The user's inputs from the dialog (report name, scope, description) are stored as global variables.


3. Variable validation

Validate that variables, like the script name, are valid and don't already exist in the saved script location.

4. Invoke the custom `Invoke-OpenAIChat` function

Invoke-OpenAIChat sends a custom one-shot prompt (including merging system instructions, knowledgebase, and user input) to OpenAI’s Chat Completion API and returns the generated response.

5. Save the script to the tree

Upon successful script generation, the module saves all generated scripts under a dedicated folder:  /sitecore/system/Modules/PowerShell/Script Library/SPExAI Report Generator/Content Reports/Reports/SPExAI Generated

6. Open, Run, or Close Dialog
After saving the script item, the module presents a modal dialog with its three choices:

1. Open Script Item – jumps to the new item in the Content Editor
2. Run Report – immediately executes the report using Invoke-Script
3. Close – exits with no action



Video Demo

As part of the entry, a video demo is required. You can check it out here:



Some Final Thoughts

If you haven’t seen it, fellow long-time MVP Rodrigo Peplau compiled a list of this year's submissions - all worth checking out. 

The quality of entries this year made it hard to predict how things would shake out. Winning was unexpected, but also an absolute honor.

Bummed I couldn't be at SUGCON EU to accept the award in person, but luckily the announcement was recorded. 😀  I will cherish this screenshot for all time:


Each year I've participated (whether on a team or solo), I've come away with valuable hackathon experience and a solid module, or at least the beginnings of one, that I could share and expand on further. I've always enjoyed the satisfaction of shipping something interesting and useful to others under competitive pressure. 

If you’re considering participating next year, I highly encourage it.  About 20% of the teams are solo, but it's not for everyone.  I recommend grouping up with others, especially if it's your first Hackathon. 

It’s a great way to push yourself, learn something new, make connections, and contribute to the spirit of the Sitecore community.

Keep on hackin'! 👨‍💻

Thursday, April 17, 2025

Sitecore Container Prerequisites Script Updates



Heads up!  I’ve made some recent updates to the open source Sitecore Container Prerequisites script to keep things aligned with the latest Sitecore versions and development environments.

What’s new:

  • ✅ Added support for Sitecore 10.3.2 and 10.4.0

  • 🖥️ Improved OS compatibility checks for Windows 10 and 11

  • 📄 Refined the README with clearer instructions for installation, usage, and contributing

  • 🔗 Updated package download links and references to current installation guides

Sitecore Container Prerequisites script remains a helpful utility for preparing your Windows machine to run Sitecore containerized environments smoothly. 

Feedback and contributions are always welcome!

📍 View the GitHub repo

Saturday, March 22, 2025

Using Sitecore Indexes in PowerShell-Driven Multilist Datasources


If you didn't know, you can point a Sitecore field's datasource to a PowerShell script. It's a super clean way to make dynamic picklists, filtering based on the current item, tags, templates, relationships, you name it.

But if you're pulling a large set of items, you really want to use the search index.

That's where things get weird.

The Find-Item command gives you fast results… but they aren't real Sitecore items. They're search result objects; great for speed, not so great for populating a multilist. Sitecore expects actual items, and when it doesn't get them, your field ends up looking empty.

Luckly, you don't have to abandon the approach completely. The fix is actually a pretty straightforward.


Some Context

For context, you can set the datasource for a multilist to be driven via a script in SPE like this:

In the script definition itself, you can write PowerShell to obtain some set of items from the tree. The resulting list is what shows as applicable for selection on the field.

In theory, you should be able to also utilize the Find-Item commandlet to obtain a list of items from the index. In my case was necessary due the performance implications of running a Get-ChildItem against a massive subtree.

First attempt looked something like this:

So far, so good. You get back a list of items. Or do you?


The Catch

The objects in the $list variable returned by Find-Item are not Sitecore items. They're dynamic search result objects that look like items, walk like items, but won't work in your multilist unless they quack like items.

If you try to return them as-is from your script, you'll find that, even if items were found in the index, the multilist fails to render the items for selection.

The fix? Pretty simple actuallu: Transform the search results back into legit Sitecore items.

Put it all together and you're golden

Now your multilist knows what to do. The search is lightning fast thanks to the index, and authors can pick from relevant matches without sifting through the entire tree.


Why This Matters

This pattern shines when you're working with large content trees or complex tagging structures where traditional item traversal would be painfully slow. By using the index, you're offloading the heavy lifting to Solr, gaining serious performance without sacrificing editor experience.

But more importantly, it calls out a subtle, easy-to-miss SPE gotcha: not all objects returned from PowerShell helpers are Sitecore items. If you're using Find-Item, you'll almost always need a second pass to resolve those results into actual items before they'll work in a field context.

Fail to do that, and you might spend hours wondering why your multilist is coming up empty, despite the index finding exactly what you wanted.

Happy datasourcing! 🚀

Friday, February 28, 2025

Sitecore Security: Are These 2023 CVEs Still a Risk?


Security in Sitecore is always evolving, and if you're not keeping an eye on the latest CVEs, you might find yourself on the wrong end of a security bulletin scramble.

Recently, a set of CVEs related to Sitecore PageDesigner have resurfaced with an increased severity rating from NIST (National Institute of Standards and Technology, the U.S. agency responsible for maintaining the National Vulnerability Database and setting cybersecurity standards), prompting the question:

Are these vulnerabilities already covered in Sitecore's official security bulletin SC2024-001-619349?

The short answer: not entirely. But let's break it down.

The CVEs in Question

Back in March 2023, security researchers uncovered a set of zero-day vulnerabilities in Sitecore PageDesigner that could allow attackers to exploit weaknesses in how Sitecore handles file paths and serialized data.

These vulnerabilities were later classified under three CVE (Common Vulnerabilities and Exposures) IDs:

  • CVE-2023-27066 - Directory Traversal: Allows authenticated attackers to download arbitrary files via UrlHandle.

  • CVE-2023-27067 - Directory Traversal: Allows remote attackers to download arbitrary files via a crafted request to download.aspx.

  • CVE-2023-27068 - Deserialization of Untrusted Data: Enables remote attackers to execute arbitrary code through ValidationResult.aspx

How These Vulnerabilities Work

The original Sitecore PageDesigner flaws were discovered in how Sitecore handled URL parameters and session values within specific backend pages. Here’s a breakdown of the two primary attack vectors:

First: Directory Traversal (CVE-2023-27066 & CVE-2023-27067)
The download.aspx page in Sitecore allowed attackers to manipulate file paths using ../ sequences, potentially granting access to sensitive files like web.config.

Normally, Sitecore prevents direct user input in these cases.

However, a flaw in Sitecore’s internal UrlHandle mechanism made it possible for an attacker to forge requests that bypassed these protections.

Second: Insecure Deserialization (CVE-2023-27068)

Sitecore PageDesigner’s session handling stored data in an unprotected format, allowing an attacker to inject malicious serialized objects.

This vulnerability could lead to remote code execution (RCE) if exploited correctly, making it the most severe issue among the three.

Why These CVEs Matter Now

At the time of discovery, the recommended fix was to upgrade to Sitecore 10.3.0 rev. 008463 or later. However, as of January 28, 2025, the severity rankings for these three CVEs has been increased.


Sitecore’s Response

After reaching out to Sitecore Support, I got clarification specifically regarding CVE-2023-27067:

CVE-2023-27067 is related to bug #390129, which was fixed in Sitecore 10.3.

Sitecore classifies this issue as low priority because it requires an authenticated user to exploit, meaning there is no risk of an anonymous attack.

This CVE is NOT included in Security Bulletin SC2024-001-619349 (KB1003408).

So, while CVE-2023-27067 is real, Sitecore does not consider it critical enough to be included in an official security bulletin.



Workarounds & Mitigation

If upgrading to Sitecore 10.3 isn't an immediate option, Sitecore provides a simple workaround:

🔧 Delete the following file:

  • /sitecore/shell/Applications/Layouts/PageDesigner/PageDesigner.xaml.xml

This file is tied to a deprecated layout editor (used for editing ASPX markup), and removing it does not impact any core Sitecore functionality.

For those running older Sitecore versions <10.3, this is a quick and effective way to mitigate risk until an upgrade is possible.


Final Thoughts

It’s easy to assume that a security bulletin will cover every vulnerability, but in this case, SC2024-001-619349 (KB1003408) does NOT include CVE-2023-27067. However, the issue was addressed in Sitecore 10.3, and for those who haven’t upgraded yet, removing a single deprecated file provides an immediate workaround.

If you haven't yet, check your environment, apply the necessary mitigation, and as always, stay on top of those Sitecore security bulletin updates!


Happy securing! 🔐